aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/acpi/method-customizing.txt66
-rw-r--r--Documentation/feature-removal-schedule.txt19
-rw-r--r--Documentation/laptops/thinkpad-acpi.txt114
-rw-r--r--Documentation/thermal/sysfs-api.txt1
-rw-r--r--arch/x86/kernel/acpi/cstate.c2
-rw-r--r--drivers/acpi/acpi_pad.c3
-rw-r--r--drivers/acpi/acpica/acnamesp.h9
-rw-r--r--drivers/acpi/acpica/acobject.h6
-rw-r--r--drivers/acpi/acpica/dsmethod.c2
-rw-r--r--drivers/acpi/acpica/dswload.c64
-rw-r--r--drivers/acpi/acpica/evregion.c4
-rw-r--r--drivers/acpi/acpica/evrgnini.c15
-rw-r--r--drivers/acpi/acpica/evxface.c4
-rw-r--r--drivers/acpi/acpica/evxfevnt.c4
-rw-r--r--drivers/acpi/acpica/evxfregn.c4
-rw-r--r--drivers/acpi/acpica/exmutex.c18
-rw-r--r--drivers/acpi/acpica/nsaccess.c2
-rw-r--r--drivers/acpi/acpica/nsdump.c2
-rw-r--r--drivers/acpi/acpica/nseval.c18
-rw-r--r--drivers/acpi/acpica/nsnames.c2
-rw-r--r--drivers/acpi/acpica/nspredef.c93
-rw-r--r--drivers/acpi/acpica/nsrepair.c447
-rw-r--r--drivers/acpi/acpica/nsrepair2.c195
-rw-r--r--drivers/acpi/acpica/nsutils.c57
-rw-r--r--drivers/acpi/acpica/nsxfeval.c10
-rw-r--r--drivers/acpi/acpica/nsxfname.c10
-rw-r--r--drivers/acpi/acpica/nsxfobj.c14
-rw-r--r--drivers/acpi/acpica/psxface.c3
-rw-r--r--drivers/acpi/acpica/rsxface.c2
-rw-r--r--drivers/acpi/acpica/utcopy.c27
-rw-r--r--drivers/acpi/battery.c2
-rw-r--r--drivers/acpi/bus.c148
-rw-r--r--drivers/acpi/button.c7
-rw-r--r--drivers/acpi/debug.c84
-rw-r--r--drivers/acpi/dock.c261
-rw-r--r--drivers/acpi/fan.c2
-rw-r--r--drivers/acpi/numa.c21
-rw-r--r--drivers/acpi/osl.c2
-rw-r--r--drivers/acpi/pci_root.c76
-rw-r--r--drivers/acpi/processor_core.c10
-rw-r--r--drivers/acpi/processor_idle.c11
-rw-r--r--drivers/acpi/processor_perflib.c50
-rw-r--r--drivers/acpi/thermal.c7
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c118
-rw-r--r--drivers/misc/Kconfig13
-rw-r--r--drivers/platform/x86/Kconfig29
-rw-r--r--drivers/platform/x86/Makefile2
-rw-r--r--drivers/platform/x86/acerhdf.c63
-rw-r--r--drivers/platform/x86/asus-laptop.c25
-rw-r--r--drivers/platform/x86/asus_acpi.c19
-rw-r--r--drivers/platform/x86/dell-laptop.c86
-rw-r--r--drivers/platform/x86/dell-wmi.c129
-rw-r--r--drivers/platform/x86/eeepc-laptop.c1415
-rw-r--r--drivers/platform/x86/hp-wmi.c139
-rw-r--r--drivers/platform/x86/msi-wmi.c293
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c1178
-rw-r--r--drivers/platform/x86/toshiba_bluetooth.c144
-rw-r--r--drivers/platform/x86/wmi.c175
-rw-r--r--drivers/pnp/pnpacpi/core.c20
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c9
-rw-r--r--drivers/thermal/thermal_sys.c19
-rw-r--r--include/acpi/acoutput.h8
-rw-r--r--include/acpi/acpixf.h2
-rw-r--r--include/acpi/processor.h5
-rw-r--r--include/linux/acpi.h23
-rw-r--r--include/linux/pnp.h13
66 files changed, 4113 insertions, 1712 deletions
diff --git a/Documentation/acpi/method-customizing.txt b/Documentation/acpi/method-customizing.txt
new file mode 100644
index 000000000000..e628cd23ca80
--- /dev/null
+++ b/Documentation/acpi/method-customizing.txt
@@ -0,0 +1,66 @@
1Linux ACPI Custom Control Method How To
2=======================================
3
4Written by Zhang Rui <rui.zhang@intel.com>
5
6
7Linux supports customizing ACPI control methods at runtime.
8
9Users can use this to
101. override an existing method which may not work correctly,
11 or just for debugging purposes.
122. insert a completely new method in order to create a missing
13 method such as _OFF, _ON, _STA, _INI, etc.
14For these cases, it is far simpler to dynamically install a single
15control method rather than override the entire DSDT, because kernel
16rebuild/reboot is not needed and test result can be got in minutes.
17
18Note: Only ACPI METHOD can be overridden, any other object types like
19 "Device", "OperationRegion", are not recognized.
20Note: The same ACPI control method can be overridden for many times,
21 and it's always the latest one that used by Linux/kernel.
22
231. override an existing method
24 a) get the ACPI table via ACPI sysfs I/F. e.g. to get the DSDT,
25 just run "cat /sys/firmware/acpi/tables/DSDT > /tmp/dsdt.dat"
26 b) disassemble the table by running "iasl -d dsdt.dat".
27 c) rewrite the ASL code of the method and save it in a new file,
28 d) package the new file (psr.asl) to an ACPI table format.
29 Here is an example of a customized \_SB._AC._PSR method,
30
31 DefinitionBlock ("", "SSDT", 1, "", "", 0x20080715)
32 {
33 External (ACON)
34
35 Method (\_SB_.AC._PSR, 0, NotSerialized)
36 {
37 Store ("In AC _PSR", Debug)
38 Return (ACON)
39 }
40 }
41 Note that the full pathname of the method in ACPI namespace
42 should be used.
43 And remember to use "External" to declare external objects.
44 e) assemble the file to generate the AML code of the method.
45 e.g. "iasl psr.asl" (psr.aml is generated as a result)
46 f) mount debugfs by "mount -t debugfs none /sys/kernel/debug"
47 g) override the old method via the debugfs by running
48 "cat /tmp/psr.aml > /sys/kernel/debug/acpi/custom_method"
49
502. insert a new method
51 This is easier than overriding an existing method.
52 We just need to create the ASL code of the method we want to
53 insert and then follow the step c) ~ g) in section 1.
54
553. undo your changes
56 The "undo" operation is not supported for a new inserted method
57 right now, i.e. we can not remove a method currently.
58 For an overrided method, in order to undo your changes, please
59 save a copy of the method original ASL code in step c) section 1,
60 and redo step c) ~ g) to override the method with the original one.
61
62
63Note: We can use a kernel with multiple custom ACPI method running,
64 But each individual write to debugfs can implement a SINGLE
65 method override. i.e. if we want to insert/override multiple
66 ACPI methods, we need to redo step c) ~ g) for multiple times.
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 21ab9357326d..870d190fe617 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -474,3 +474,22 @@ Why: Obsoleted by the adt7475 driver.
474Who: Jean Delvare <khali@linux-fr.org> 474Who: Jean Delvare <khali@linux-fr.org>
475 475
476--------------------------- 476---------------------------
477What: Support for lcd_switch and display_get in asus-laptop driver
478When: March 2010
479Why: These two features use non-standard interfaces. There are the
480 only features that really need multiple path to guess what's
481 the right method name on a specific laptop.
482
483 Removing them will allow to remove a lot of code an significantly
484 clean the drivers.
485
486 This will affect the backlight code which won't be able to know
487 if the backlight is on or off. The platform display file will also be
488 write only (like the one in eeepc-laptop).
489
490 This should'nt affect a lot of user because they usually know
491 when their display is on or off.
492
493Who: Corentin Chary <corentin.chary@gmail.com>
494
495----------------------------
diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt
index aafcaa634191..169091f75e6d 100644
--- a/Documentation/laptops/thinkpad-acpi.txt
+++ b/Documentation/laptops/thinkpad-acpi.txt
@@ -1,7 +1,7 @@
1 ThinkPad ACPI Extras Driver 1 ThinkPad ACPI Extras Driver
2 2
3 Version 0.23 3 Version 0.24
4 April 10th, 2009 4 December 11th, 2009
5 5
6 Borislav Deianov <borislav@users.sf.net> 6 Borislav Deianov <borislav@users.sf.net>
7 Henrique de Moraes Holschuh <hmh@hmh.eng.br> 7 Henrique de Moraes Holschuh <hmh@hmh.eng.br>
@@ -460,6 +460,8 @@ event code Key Notes
460 For Lenovo ThinkPads with a new 460 For Lenovo ThinkPads with a new
461 BIOS, it has to be handled either 461 BIOS, it has to be handled either
462 by the ACPI OSI, or by userspace. 462 by the ACPI OSI, or by userspace.
463 The driver does the right thing,
464 never mess with this.
4630x1011 0x10 FN+END Brightness down. See brightness 4650x1011 0x10 FN+END Brightness down. See brightness
464 up for details. 466 up for details.
465 467
@@ -582,46 +584,15 @@ with hotkey_report_mode.
582 584
583Brightness hotkey notes: 585Brightness hotkey notes:
584 586
585These are the current sane choices for brightness key mapping in 587Don't mess with the brightness hotkeys in a Thinkpad. If you want
586thinkpad-acpi: 588notifications for OSD, use the sysfs backlight class event support.
587 589
588For IBM and Lenovo models *without* ACPI backlight control (the ones on 590The driver will issue KEY_BRIGHTNESS_UP and KEY_BRIGHTNESS_DOWN events
589which thinkpad-acpi will autoload its backlight interface by default, 591automatically for the cases were userspace has to do something to
590and on which ACPI video does not export a backlight interface): 592implement brightness changes. When you override these events, you will
591 593either fail to handle properly the ThinkPads that require explicit
5921. Don't enable or map the brightness hotkeys in thinkpad-acpi, as 594action to change backlight brightness, or the ThinkPads that require
593 these older firmware versions unfortunately won't respect the hotkey 595that no action be taken to work properly.
594 mask for brightness keys anyway, and always reacts to them. This
595 usually work fine, unless X.org drivers are doing something to block
596 the BIOS. In that case, use (3) below. This is the default mode of
597 operation.
598
5992. Enable the hotkeys, but map them to something else that is NOT
600 KEY_BRIGHTNESS_UP/DOWN or any other keycode that would cause
601 userspace to try to change the backlight level, and use that as an
602 on-screen-display hint.
603
6043. IF AND ONLY IF X.org drivers find a way to block the firmware from
605 automatically changing the brightness, enable the hotkeys and map
606 them to KEY_BRIGHTNESS_UP and KEY_BRIGHTNESS_DOWN, and feed that to
607 something that calls xbacklight. thinkpad-acpi will not be able to
608 change brightness in that case either, so you should disable its
609 backlight interface.
610
611For Lenovo models *with* ACPI backlight control:
612
6131. Load up ACPI video and use that. ACPI video will report ACPI
614 events for brightness change keys. Do not mess with thinkpad-acpi
615 defaults in this case. thinkpad-acpi should not have anything to do
616 with backlight events in a scenario where ACPI video is loaded:
617 brightness hotkeys must be disabled, and the backlight interface is
618 to be kept disabled as well. This is the default mode of operation.
619
6202. Do *NOT* load up ACPI video, enable the hotkeys in thinkpad-acpi,
621 and map them to KEY_BRIGHTNESS_UP and KEY_BRIGHTNESS_DOWN. Process
622 these keys on userspace somehow (e.g. by calling xbacklight).
623 The driver will do this automatically if it detects that ACPI video
624 has been disabled.
625 596
626 597
627Bluetooth 598Bluetooth
@@ -1121,25 +1092,61 @@ WARNING:
1121 its level up and down at every change. 1092 its level up and down at every change.
1122 1093
1123 1094
1124Volume control -- /proc/acpi/ibm/volume 1095Volume control
1125--------------------------------------- 1096--------------
1097
1098procfs: /proc/acpi/ibm/volume
1099ALSA: "ThinkPad Console Audio Control", default ID: "ThinkPadEC"
1100
1101NOTE: by default, the volume control interface operates in read-only
1102mode, as it is supposed to be used for on-screen-display purposes.
1103The read/write mode can be enabled through the use of the
1104"volume_control=1" module parameter.
1126 1105
1127This feature allows volume control on ThinkPad models which don't have 1106NOTE: distros are urged to not enable volume_control by default, this
1128a hardware volume knob. The available commands are: 1107should be done by the local admin only. The ThinkPad UI is for the
1108console audio control to be done through the volume keys only, and for
1109the desktop environment to just provide on-screen-display feedback.
1110Software volume control should be done only in the main AC97/HDA
1111mixer.
1112
1113This feature allows volume control on ThinkPad models with a digital
1114volume knob (when available, not all models have it), as well as
1115mute/unmute control. The available commands are:
1129 1116
1130 echo up >/proc/acpi/ibm/volume 1117 echo up >/proc/acpi/ibm/volume
1131 echo down >/proc/acpi/ibm/volume 1118 echo down >/proc/acpi/ibm/volume
1132 echo mute >/proc/acpi/ibm/volume 1119 echo mute >/proc/acpi/ibm/volume
1120 echo unmute >/proc/acpi/ibm/volume
1133 echo 'level <level>' >/proc/acpi/ibm/volume 1121 echo 'level <level>' >/proc/acpi/ibm/volume
1134 1122
1135The <level> number range is 0 to 15 although not all of them may be 1123The <level> number range is 0 to 14 although not all of them may be
1136distinct. The unmute the volume after the mute command, use either the 1124distinct. The unmute the volume after the mute command, use either the
1137up or down command (the level command will not unmute the volume). 1125up or down command (the level command will not unmute the volume), or
1126the unmute command.
1127
1138The current volume level and mute state is shown in the file. 1128The current volume level and mute state is shown in the file.
1139 1129
1140The ALSA mixer interface to this feature is still missing, but patches 1130You can use the volume_capabilities parameter to tell the driver
1141to add it exist. That problem should be addressed in the not so 1131whether your thinkpad has volume control or mute-only control:
1142distant future. 1132volume_capabilities=1 for mixers with mute and volume control,
1133volume_capabilities=2 for mixers with only mute control.
1134
1135If the driver misdetects the capabilities for your ThinkPad model,
1136please report this to ibm-acpi-devel@lists.sourceforge.net, so that we
1137can update the driver.
1138
1139There are two strategies for volume control. To select which one
1140should be used, use the volume_mode module parameter: volume_mode=1
1141selects EC mode, and volume_mode=3 selects EC mode with NVRAM backing
1142(so that volume/mute changes are remembered across shutdown/reboot).
1143
1144The driver will operate in volume_mode=3 by default. If that does not
1145work well on your ThinkPad model, please report this to
1146ibm-acpi-devel@lists.sourceforge.net.
1147
1148The driver supports the standard ALSA module parameters. If the ALSA
1149mixer is disabled, the driver will disable all volume functionality.
1143 1150
1144 1151
1145Fan control and monitoring: fan speed, fan enable/disable 1152Fan control and monitoring: fan speed, fan enable/disable
@@ -1405,6 +1412,7 @@ to enable more than one output class, just add their values.
1405 0x0008 HKEY event interface, hotkeys 1412 0x0008 HKEY event interface, hotkeys
1406 0x0010 Fan control 1413 0x0010 Fan control
1407 0x0020 Backlight brightness 1414 0x0020 Backlight brightness
1415 0x0040 Audio mixer/volume control
1408 1416
1409There is also a kernel build option to enable more debugging 1417There is also a kernel build option to enable more debugging
1410information, which may be necessary to debug driver problems. 1418information, which may be necessary to debug driver problems.
@@ -1465,3 +1473,9 @@ Sysfs interface changelog:
1465 and it is always able to disable hot keys. Very old 1473 and it is always able to disable hot keys. Very old
1466 thinkpads are properly supported. hotkey_bios_mask 1474 thinkpads are properly supported. hotkey_bios_mask
1467 is deprecated and marked for removal. 1475 is deprecated and marked for removal.
1476
14770x020600: Marker for backlight change event support.
1478
14790x020700: Support for mute-only mixers.
1480 Volume control in read-only mode by default.
1481 Marker for ALSA mixer support.
diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt
index a87dc277a5ca..cb3d15bc1aeb 100644
--- a/Documentation/thermal/sysfs-api.txt
+++ b/Documentation/thermal/sysfs-api.txt
@@ -206,6 +206,7 @@ passive
206 passive trip point for the zone. Activation is done by polling with 206 passive trip point for the zone. Activation is done by polling with
207 an interval of 1 second. 207 an interval of 1 second.
208 Unit: millidegrees Celsius 208 Unit: millidegrees Celsius
209 Valid values: 0 (disabled) or greater than 1000
209 RW, Optional 210 RW, Optional
210 211
211***************************** 212*****************************
diff --git a/arch/x86/kernel/acpi/cstate.c b/arch/x86/kernel/acpi/cstate.c
index 59cdfa4686b2..2e837f5080fe 100644
--- a/arch/x86/kernel/acpi/cstate.c
+++ b/arch/x86/kernel/acpi/cstate.c
@@ -48,7 +48,7 @@ void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags,
48 * P4, Core and beyond CPUs 48 * P4, Core and beyond CPUs
49 */ 49 */
50 if (c->x86_vendor == X86_VENDOR_INTEL && 50 if (c->x86_vendor == X86_VENDOR_INTEL &&
51 (c->x86 > 0xf || (c->x86 == 6 && c->x86_model >= 14))) 51 (c->x86 > 0xf || (c->x86 == 6 && c->x86_model >= 0x0f)))
52 flags->bm_control = 0; 52 flags->bm_control = 0;
53} 53}
54EXPORT_SYMBOL(acpi_processor_power_init_bm_check); 54EXPORT_SYMBOL(acpi_processor_power_init_bm_check);
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c
index 0d2cdb86158b..97991ac6f5fc 100644
--- a/drivers/acpi/acpi_pad.c
+++ b/drivers/acpi/acpi_pad.c
@@ -100,7 +100,8 @@ static void round_robin_cpu(unsigned int tsk_index)
100 struct cpumask *pad_busy_cpus = to_cpumask(pad_busy_cpus_bits); 100 struct cpumask *pad_busy_cpus = to_cpumask(pad_busy_cpus_bits);
101 cpumask_var_t tmp; 101 cpumask_var_t tmp;
102 int cpu; 102 int cpu;
103 unsigned long min_weight = -1, preferred_cpu; 103 unsigned long min_weight = -1;
104 unsigned long uninitialized_var(preferred_cpu);
104 105
105 if (!alloc_cpumask_var(&tmp, GFP_KERNEL)) 106 if (!alloc_cpumask_var(&tmp, GFP_KERNEL))
106 return; 107 return;
diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h
index ab83919dda61..61edb156e8d0 100644
--- a/drivers/acpi/acpica/acnamesp.h
+++ b/drivers/acpi/acpica/acnamesp.h
@@ -296,6 +296,11 @@ acpi_ns_complex_repairs(struct acpi_predefined_data *data,
296 acpi_status validate_status, 296 acpi_status validate_status,
297 union acpi_operand_object **return_object_ptr); 297 union acpi_operand_object **return_object_ptr);
298 298
299void
300acpi_ns_remove_null_elements(struct acpi_predefined_data *data,
301 u8 package_type,
302 union acpi_operand_object *obj_desc);
303
299/* 304/*
300 * nssearch - Namespace searching and entry 305 * nssearch - Namespace searching and entry
301 */ 306 */
@@ -354,9 +359,7 @@ acpi_ns_externalize_name(u32 internal_name_length,
354 const char *internal_name, 359 const char *internal_name,
355 u32 * converted_name_length, char **converted_name); 360 u32 * converted_name_length, char **converted_name);
356 361
357struct acpi_namespace_node *acpi_ns_map_handle_to_node(acpi_handle handle); 362struct acpi_namespace_node *acpi_ns_validate_handle(acpi_handle handle);
358
359acpi_handle acpi_ns_convert_entry_to_handle(struct acpi_namespace_node *node);
360 363
361void acpi_ns_terminate(void); 364void acpi_ns_terminate(void);
362 365
diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h
index b39d682a2140..64062b1be3ee 100644
--- a/drivers/acpi/acpica/acobject.h
+++ b/drivers/acpi/acpica/acobject.h
@@ -180,7 +180,11 @@ struct acpi_object_method {
180 u8 sync_level; 180 u8 sync_level;
181 union acpi_operand_object *mutex; 181 union acpi_operand_object *mutex;
182 u8 *aml_start; 182 u8 *aml_start;
183 ACPI_INTERNAL_METHOD implementation; 183 union {
184 ACPI_INTERNAL_METHOD implementation;
185 union acpi_operand_object *handler;
186 } extra;
187
184 u32 aml_length; 188 u32 aml_length;
185 u8 thread_count; 189 u8 thread_count;
186 acpi_owner_id owner_id; 190 acpi_owner_id owner_id;
diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c
index 567a4899a018..e786f9fd767f 100644
--- a/drivers/acpi/acpica/dsmethod.c
+++ b/drivers/acpi/acpica/dsmethod.c
@@ -414,7 +414,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread,
414 /* Invoke an internal method if necessary */ 414 /* Invoke an internal method if necessary */
415 415
416 if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { 416 if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) {
417 status = obj_desc->method.implementation(next_walk_state); 417 status = obj_desc->method.extra.implementation(next_walk_state);
418 if (status == AE_OK) { 418 if (status == AE_OK) {
419 status = AE_CTRL_TERMINATE; 419 status = AE_CTRL_TERMINATE;
420 } 420 }
diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c
index 10fc78517843..b40513dd6a6a 100644
--- a/drivers/acpi/acpica/dswload.c
+++ b/drivers/acpi/acpica/dswload.c
@@ -212,18 +212,19 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state,
212 case ACPI_TYPE_BUFFER: 212 case ACPI_TYPE_BUFFER:
213 213
214 /* 214 /*
215 * These types we will allow, but we will change the type. This 215 * These types we will allow, but we will change the type.
216 * enables some existing code of the form: 216 * This enables some existing code of the form:
217 * 217 *
218 * Name (DEB, 0) 218 * Name (DEB, 0)
219 * Scope (DEB) { ... } 219 * Scope (DEB) { ... }
220 * 220 *
221 * Note: silently change the type here. On the second pass, we will report 221 * Note: silently change the type here. On the second pass,
222 * a warning 222 * we will report a warning
223 */ 223 */
224 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 224 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
225 "Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)\n", 225 "Type override - [%4.4s] had invalid type (%s) "
226 path, 226 "for Scope operator, changed to type ANY\n",
227 acpi_ut_get_node_name(node),
227 acpi_ut_get_type_name(node->type))); 228 acpi_ut_get_type_name(node->type)));
228 229
229 node->type = ACPI_TYPE_ANY; 230 node->type = ACPI_TYPE_ANY;
@@ -235,8 +236,10 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state,
235 /* All other types are an error */ 236 /* All other types are an error */
236 237
237 ACPI_ERROR((AE_INFO, 238 ACPI_ERROR((AE_INFO,
238 "Invalid type (%s) for target of Scope operator [%4.4s] (Cannot override)", 239 "Invalid type (%s) for target of "
239 acpi_ut_get_type_name(node->type), path)); 240 "Scope operator [%4.4s] (Cannot override)",
241 acpi_ut_get_type_name(node->type),
242 acpi_ut_get_node_name(node)));
240 243
241 return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 244 return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
242 } 245 }
@@ -697,15 +700,16 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
697 case ACPI_TYPE_BUFFER: 700 case ACPI_TYPE_BUFFER:
698 701
699 /* 702 /*
700 * These types we will allow, but we will change the type. This 703 * These types we will allow, but we will change the type.
701 * enables some existing code of the form: 704 * This enables some existing code of the form:
702 * 705 *
703 * Name (DEB, 0) 706 * Name (DEB, 0)
704 * Scope (DEB) { ... } 707 * Scope (DEB) { ... }
705 */ 708 */
706 ACPI_WARNING((AE_INFO, 709 ACPI_WARNING((AE_INFO,
707 "Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)", 710 "Type override - [%4.4s] had invalid type (%s) "
708 buffer_ptr, 711 "for Scope operator, changed to type ANY\n",
712 acpi_ut_get_node_name(node),
709 acpi_ut_get_type_name(node->type))); 713 acpi_ut_get_type_name(node->type)));
710 714
711 node->type = ACPI_TYPE_ANY; 715 node->type = ACPI_TYPE_ANY;
@@ -717,9 +721,10 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
717 /* All other types are an error */ 721 /* All other types are an error */
718 722
719 ACPI_ERROR((AE_INFO, 723 ACPI_ERROR((AE_INFO,
720 "Invalid type (%s) for target of Scope operator [%4.4s]", 724 "Invalid type (%s) for target of "
725 "Scope operator [%4.4s] (Cannot override)",
721 acpi_ut_get_type_name(node->type), 726 acpi_ut_get_type_name(node->type),
722 buffer_ptr)); 727 acpi_ut_get_node_name(node)));
723 728
724 return (AE_AML_OPERAND_TYPE); 729 return (AE_AML_OPERAND_TYPE);
725 } 730 }
@@ -1047,9 +1052,22 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
1047 } 1052 }
1048 1053
1049 /* 1054 /*
1050 * If we are executing a method, initialize the region 1055 * The op_region is not fully parsed at this time. The only valid
1056 * argument is the space_id. (We must save the address of the
1057 * AML of the address and length operands)
1058 *
1059 * If we have a valid region, initialize it. The namespace is
1060 * unlocked at this point.
1061 *
1062 * Need to unlock interpreter if it is locked (if we are running
1063 * a control method), in order to allow _REG methods to be run
1064 * during acpi_ev_initialize_region.
1051 */ 1065 */
1052 if (walk_state->method_node) { 1066 if (walk_state->method_node) {
1067 /*
1068 * Executing a method: initialize the region and unlock
1069 * the interpreter
1070 */
1053 status = 1071 status =
1054 acpi_ex_create_region(op->named.data, 1072 acpi_ex_create_region(op->named.data,
1055 op->named.length, 1073 op->named.length,
@@ -1058,21 +1076,17 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
1058 if (ACPI_FAILURE(status)) { 1076 if (ACPI_FAILURE(status)) {
1059 return (status); 1077 return (status);
1060 } 1078 }
1061 }
1062 1079
1063 /* 1080 acpi_ex_exit_interpreter();
1064 * The op_region is not fully parsed at this time. Only valid 1081 }
1065 * argument is the space_id. (We must save the address of the
1066 * AML of the address and length operands)
1067 */
1068 1082
1069 /*
1070 * If we have a valid region, initialize it
1071 * Namespace is NOT locked at this point.
1072 */
1073 status = 1083 status =
1074 acpi_ev_initialize_region 1084 acpi_ev_initialize_region
1075 (acpi_ns_get_attached_object(node), FALSE); 1085 (acpi_ns_get_attached_object(node), FALSE);
1086 if (walk_state->method_node) {
1087 acpi_ex_enter_interpreter();
1088 }
1089
1076 if (ACPI_FAILURE(status)) { 1090 if (ACPI_FAILURE(status)) {
1077 /* 1091 /*
1078 * If AE_NOT_EXIST is returned, it is not fatal 1092 * If AE_NOT_EXIST is returned, it is not fatal
diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c
index 0bc807c33a56..5336d911fbf0 100644
--- a/drivers/acpi/acpica/evregion.c
+++ b/drivers/acpi/acpica/evregion.c
@@ -718,7 +718,7 @@ acpi_ev_install_handler(acpi_handle obj_handle,
718 718
719 /* Convert and validate the device handle */ 719 /* Convert and validate the device handle */
720 720
721 node = acpi_ns_map_handle_to_node(obj_handle); 721 node = acpi_ns_validate_handle(obj_handle);
722 if (!node) { 722 if (!node) {
723 return (AE_BAD_PARAMETER); 723 return (AE_BAD_PARAMETER);
724 } 724 }
@@ -1087,7 +1087,7 @@ acpi_ev_reg_run(acpi_handle obj_handle,
1087 1087
1088 /* Convert and validate the device handle */ 1088 /* Convert and validate the device handle */
1089 1089
1090 node = acpi_ns_map_handle_to_node(obj_handle); 1090 node = acpi_ns_validate_handle(obj_handle);
1091 if (!node) { 1091 if (!node) {
1092 return (AE_BAD_PARAMETER); 1092 return (AE_BAD_PARAMETER);
1093 } 1093 }
diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c
index cf29c4953028..ff168052a332 100644
--- a/drivers/acpi/acpica/evrgnini.c
+++ b/drivers/acpi/acpica/evrgnini.c
@@ -575,6 +575,21 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj,
575 handler_obj = obj_desc->thermal_zone.handler; 575 handler_obj = obj_desc->thermal_zone.handler;
576 break; 576 break;
577 577
578 case ACPI_TYPE_METHOD:
579 /*
580 * If we are executing module level code, the original
581 * Node's object was replaced by this Method object and we
582 * saved the handler in the method object.
583 *
584 * See acpi_ns_exec_module_code
585 */
586 if (obj_desc->method.
587 flags & AOPOBJ_MODULE_LEVEL) {
588 handler_obj =
589 obj_desc->method.extra.handler;
590 }
591 break;
592
578 default: 593 default:
579 /* Ignore other objects */ 594 /* Ignore other objects */
580 break; 595 break;
diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c
index 10b8543dd466..2fe0809d4eb2 100644
--- a/drivers/acpi/acpica/evxface.c
+++ b/drivers/acpi/acpica/evxface.c
@@ -259,7 +259,7 @@ acpi_install_notify_handler(acpi_handle device,
259 259
260 /* Convert and validate the device handle */ 260 /* Convert and validate the device handle */
261 261
262 node = acpi_ns_map_handle_to_node(device); 262 node = acpi_ns_validate_handle(device);
263 if (!node) { 263 if (!node) {
264 status = AE_BAD_PARAMETER; 264 status = AE_BAD_PARAMETER;
265 goto unlock_and_exit; 265 goto unlock_and_exit;
@@ -425,7 +425,7 @@ acpi_remove_notify_handler(acpi_handle device,
425 425
426 /* Convert and validate the device handle */ 426 /* Convert and validate the device handle */
427 427
428 node = acpi_ns_map_handle_to_node(device); 428 node = acpi_ns_validate_handle(device);
429 if (!node) { 429 if (!node) {
430 status = AE_BAD_PARAMETER; 430 status = AE_BAD_PARAMETER;
431 goto unlock_and_exit; 431 goto unlock_and_exit;
diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c
index 4721f58fe42c..eed7a38d25f2 100644
--- a/drivers/acpi/acpica/evxfevnt.c
+++ b/drivers/acpi/acpica/evxfevnt.c
@@ -610,7 +610,7 @@ acpi_install_gpe_block(acpi_handle gpe_device,
610 return (status); 610 return (status);
611 } 611 }
612 612
613 node = acpi_ns_map_handle_to_node(gpe_device); 613 node = acpi_ns_validate_handle(gpe_device);
614 if (!node) { 614 if (!node) {
615 status = AE_BAD_PARAMETER; 615 status = AE_BAD_PARAMETER;
616 goto unlock_and_exit; 616 goto unlock_and_exit;
@@ -698,7 +698,7 @@ acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
698 return (status); 698 return (status);
699 } 699 }
700 700
701 node = acpi_ns_map_handle_to_node(gpe_device); 701 node = acpi_ns_validate_handle(gpe_device);
702 if (!node) { 702 if (!node) {
703 status = AE_BAD_PARAMETER; 703 status = AE_BAD_PARAMETER;
704 goto unlock_and_exit; 704 goto unlock_and_exit;
diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c
index 7c3d2d356ffb..c98aa7c2d67c 100644
--- a/drivers/acpi/acpica/evxfregn.c
+++ b/drivers/acpi/acpica/evxfregn.c
@@ -89,7 +89,7 @@ acpi_install_address_space_handler(acpi_handle device,
89 89
90 /* Convert and validate the device handle */ 90 /* Convert and validate the device handle */
91 91
92 node = acpi_ns_map_handle_to_node(device); 92 node = acpi_ns_validate_handle(device);
93 if (!node) { 93 if (!node) {
94 status = AE_BAD_PARAMETER; 94 status = AE_BAD_PARAMETER;
95 goto unlock_and_exit; 95 goto unlock_and_exit;
@@ -155,7 +155,7 @@ acpi_remove_address_space_handler(acpi_handle device,
155 155
156 /* Convert and validate the device handle */ 156 /* Convert and validate the device handle */
157 157
158 node = acpi_ns_map_handle_to_node(device); 158 node = acpi_ns_validate_handle(device);
159 if (!node || 159 if (!node ||
160 ((node->type != ACPI_TYPE_DEVICE) && 160 ((node->type != ACPI_TYPE_DEVICE) &&
161 (node->type != ACPI_TYPE_PROCESSOR) && 161 (node->type != ACPI_TYPE_PROCESSOR) &&
diff --git a/drivers/acpi/acpica/exmutex.c b/drivers/acpi/acpica/exmutex.c
index 2f0114202b05..3c456bd575d0 100644
--- a/drivers/acpi/acpica/exmutex.c
+++ b/drivers/acpi/acpica/exmutex.c
@@ -375,6 +375,15 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
375 return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED); 375 return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED);
376 } 376 }
377 377
378 /* Must have a valid thread ID */
379
380 if (!walk_state->thread) {
381 ACPI_ERROR((AE_INFO,
382 "Cannot release Mutex [%4.4s], null thread info",
383 acpi_ut_get_node_name(obj_desc->mutex.node)));
384 return_ACPI_STATUS(AE_AML_INTERNAL);
385 }
386
378 /* 387 /*
379 * The Mutex is owned, but this thread must be the owner. 388 * The Mutex is owned, but this thread must be the owner.
380 * Special case for Global Lock, any thread can release 389 * Special case for Global Lock, any thread can release
@@ -392,15 +401,6 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
392 return_ACPI_STATUS(AE_AML_NOT_OWNER); 401 return_ACPI_STATUS(AE_AML_NOT_OWNER);
393 } 402 }
394 403
395 /* Must have a valid thread ID */
396
397 if (!walk_state->thread) {
398 ACPI_ERROR((AE_INFO,
399 "Cannot release Mutex [%4.4s], null thread info",
400 acpi_ut_get_node_name(obj_desc->mutex.node)));
401 return_ACPI_STATUS(AE_AML_INTERNAL);
402 }
403
404 /* 404 /*
405 * The sync level of the mutex must be equal to the current sync level. In 405 * The sync level of the mutex must be equal to the current sync level. In
406 * other words, the current level means that at least one mutex at that 406 * other words, the current level means that at least one mutex at that
diff --git a/drivers/acpi/acpica/nsaccess.c b/drivers/acpi/acpica/nsaccess.c
index 9c3cdbe2d82a..d622ba770000 100644
--- a/drivers/acpi/acpica/nsaccess.c
+++ b/drivers/acpi/acpica/nsaccess.c
@@ -165,7 +165,7 @@ acpi_status acpi_ns_root_initialize(void)
165 165
166 obj_desc->method.method_flags = 166 obj_desc->method.method_flags =
167 AML_METHOD_INTERNAL_ONLY; 167 AML_METHOD_INTERNAL_ONLY;
168 obj_desc->method.implementation = 168 obj_desc->method.extra.implementation =
169 acpi_ut_osi_implementation; 169 acpi_ut_osi_implementation;
170#endif 170#endif
171 break; 171 break;
diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c
index 2deb986861ca..e37836e27e29 100644
--- a/drivers/acpi/acpica/nsdump.c
+++ b/drivers/acpi/acpica/nsdump.c
@@ -180,7 +180,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle,
180 return (AE_OK); 180 return (AE_OK);
181 } 181 }
182 182
183 this_node = acpi_ns_map_handle_to_node(obj_handle); 183 this_node = acpi_ns_validate_handle(obj_handle);
184 if (!this_node) { 184 if (!this_node) {
185 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid object handle %p\n", 185 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid object handle %p\n",
186 obj_handle)); 186 obj_handle));
diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c
index f771e978c403..af9fe9103734 100644
--- a/drivers/acpi/acpica/nseval.c
+++ b/drivers/acpi/acpica/nseval.c
@@ -381,6 +381,18 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj,
381 method_obj->method.next_object); 381 method_obj->method.next_object);
382 type = acpi_ns_get_type(parent_node); 382 type = acpi_ns_get_type(parent_node);
383 383
384 /*
385 * Get the region handler and save it in the method object. We may need
386 * this if an operation region declaration causes a _REG method to be run.
387 *
388 * We can't do this in acpi_ps_link_module_code because
389 * acpi_gbl_root_node->Object is NULL at PASS1.
390 */
391 if ((type == ACPI_TYPE_DEVICE) && parent_node->object) {
392 method_obj->method.extra.handler =
393 parent_node->object->device.handler;
394 }
395
384 /* Must clear next_object (acpi_ns_attach_object needs the field) */ 396 /* Must clear next_object (acpi_ns_attach_object needs the field) */
385 397
386 method_obj->method.next_object = NULL; 398 method_obj->method.next_object = NULL;
@@ -415,6 +427,12 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj,
415 ACPI_DEBUG_PRINT((ACPI_DB_INIT, "Executed module-level code at %p\n", 427 ACPI_DEBUG_PRINT((ACPI_DB_INIT, "Executed module-level code at %p\n",
416 method_obj->method.aml_start)); 428 method_obj->method.aml_start));
417 429
430 /* Delete a possible implicit return value (in slack mode) */
431
432 if (info->return_object) {
433 acpi_ut_remove_reference(info->return_object);
434 }
435
418 /* Detach the temporary method object */ 436 /* Detach the temporary method object */
419 437
420 acpi_ns_detach_object(parent_node); 438 acpi_ns_detach_object(parent_node);
diff --git a/drivers/acpi/acpica/nsnames.c b/drivers/acpi/acpica/nsnames.c
index af8e6bcee07e..8f9a4875ce26 100644
--- a/drivers/acpi/acpica/nsnames.c
+++ b/drivers/acpi/acpica/nsnames.c
@@ -232,7 +232,7 @@ acpi_ns_handle_to_pathname(acpi_handle target_handle,
232 232
233 ACPI_FUNCTION_TRACE_PTR(ns_handle_to_pathname, target_handle); 233 ACPI_FUNCTION_TRACE_PTR(ns_handle_to_pathname, target_handle);
234 234
235 node = acpi_ns_map_handle_to_node(target_handle); 235 node = acpi_ns_validate_handle(target_handle);
236 if (!node) { 236 if (!node) {
237 return_ACPI_STATUS(AE_BAD_PARAMETER); 237 return_ACPI_STATUS(AE_BAD_PARAMETER);
238 } 238 }
diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c
index b05f42903c86..d34fa59548f7 100644
--- a/drivers/acpi/acpica/nspredef.c
+++ b/drivers/acpi/acpica/nspredef.c
@@ -216,29 +216,38 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node,
216 data->pathname = pathname; 216 data->pathname = pathname;
217 217
218 /* 218 /*
219 * Check that the type of the return object is what is expected for 219 * Check that the type of the main return object is what is expected
220 * this predefined name 220 * for this predefined name
221 */ 221 */
222 status = acpi_ns_check_object_type(data, return_object_ptr, 222 status = acpi_ns_check_object_type(data, return_object_ptr,
223 predefined->info.expected_btypes, 223 predefined->info.expected_btypes,
224 ACPI_NOT_PACKAGE_ELEMENT); 224 ACPI_NOT_PACKAGE_ELEMENT);
225 if (ACPI_FAILURE(status)) { 225 if (ACPI_FAILURE(status)) {
226 goto check_validation_status; 226 goto exit;
227 } 227 }
228 228
229 /* For returned Package objects, check the type of all sub-objects */ 229 /*
230 230 * For returned Package objects, check the type of all sub-objects.
231 if (return_object->common.type == ACPI_TYPE_PACKAGE) { 231 * Note: Package may have been newly created by call above.
232 */
233 if ((*return_object_ptr)->common.type == ACPI_TYPE_PACKAGE) {
232 status = acpi_ns_check_package(data, return_object_ptr); 234 status = acpi_ns_check_package(data, return_object_ptr);
235 if (ACPI_FAILURE(status)) {
236 goto exit;
237 }
233 } 238 }
234 239
235 /* 240 /*
236 * Perform additional, more complicated repairs on a per-name 241 * The return object was OK, or it was successfully repaired above.
237 * basis. 242 * Now make some additional checks such as verifying that package
243 * objects are sorted correctly (if required) or buffer objects have
244 * the correct data width (bytes vs. dwords). These repairs are
245 * performed on a per-name basis, i.e., the code is specific to
246 * particular predefined names.
238 */ 247 */
239 status = acpi_ns_complex_repairs(data, node, status, return_object_ptr); 248 status = acpi_ns_complex_repairs(data, node, status, return_object_ptr);
240 249
241check_validation_status: 250exit:
242 /* 251 /*
243 * If the object validation failed or if we successfully repaired one 252 * If the object validation failed or if we successfully repaired one
244 * or more objects, mark the parent node to suppress further warning 253 * or more objects, mark the parent node to suppress further warning
@@ -427,6 +436,13 @@ acpi_ns_check_package(struct acpi_predefined_data *data,
427 data->pathname, package->ret_info.type, 436 data->pathname, package->ret_info.type,
428 return_object->package.count)); 437 return_object->package.count));
429 438
439 /*
440 * For variable-length Packages, we can safely remove all embedded
441 * and trailing NULL package elements
442 */
443 acpi_ns_remove_null_elements(data, package->ret_info.type,
444 return_object);
445
430 /* Extract package count and elements array */ 446 /* Extract package count and elements array */
431 447
432 elements = return_object->package.elements; 448 elements = return_object->package.elements;
@@ -461,11 +477,11 @@ acpi_ns_check_package(struct acpi_predefined_data *data,
461 if (count < expected_count) { 477 if (count < expected_count) {
462 goto package_too_small; 478 goto package_too_small;
463 } else if (count > expected_count) { 479 } else if (count > expected_count) {
464 ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, 480 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
465 data->node_flags, 481 "%s: Return Package is larger than needed - "
466 "Return Package is larger than needed - " 482 "found %u, expected %u\n",
467 "found %u, expected %u", count, 483 data->pathname, count,
468 expected_count)); 484 expected_count));
469 } 485 }
470 486
471 /* Validate all elements of the returned package */ 487 /* Validate all elements of the returned package */
@@ -680,53 +696,18 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data,
680 union acpi_operand_object *sub_package; 696 union acpi_operand_object *sub_package;
681 union acpi_operand_object **sub_elements; 697 union acpi_operand_object **sub_elements;
682 acpi_status status; 698 acpi_status status;
683 u8 non_trailing_null = FALSE;
684 u32 expected_count; 699 u32 expected_count;
685 u32 i; 700 u32 i;
686 u32 j; 701 u32 j;
687 702
688 /* Validate each sub-Package in the parent Package */ 703 /*
689 704 * Validate each sub-Package in the parent Package
705 *
706 * NOTE: assumes list of sub-packages contains no NULL elements.
707 * Any NULL elements should have been removed by earlier call
708 * to acpi_ns_remove_null_elements.
709 */
690 for (i = 0; i < count; i++) { 710 for (i = 0; i < count; i++) {
691 /*
692 * Handling for NULL package elements. For now, we will simply allow
693 * a parent package with trailing NULL elements. This can happen if
694 * the package was defined to be longer than the initializer list.
695 * This is legal as per the ACPI specification. It is often used
696 * to allow for dynamic initialization of a Package.
697 *
698 * A future enhancement may be to simply truncate the package to
699 * remove the trailing NULL elements.
700 */
701 if (!(*elements)) {
702 if (!non_trailing_null) {
703
704 /* Ensure the remaining elements are all NULL */
705
706 for (j = 1; j < (count - i + 1); j++) {
707 if (elements[j]) {
708 non_trailing_null = TRUE;
709 }
710 }
711
712 if (!non_trailing_null) {
713
714 /* Ignore the trailing NULL elements */
715
716 return (AE_OK);
717 }
718 }
719
720 /* There are trailing non-null elements, issue warning */
721
722 ACPI_WARN_PREDEFINED((AE_INFO, data->pathname,
723 data->node_flags,
724 "Found NULL element at package index %u",
725 i));
726 elements++;
727 continue;
728 }
729
730 sub_package = *elements; 711 sub_package = *elements;
731 sub_elements = sub_package->package.elements; 712 sub_elements = sub_package->package.elements;
732 713
diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c
index d563f1a564a7..4fd1bdb056b2 100644
--- a/drivers/acpi/acpica/nsrepair.c
+++ b/drivers/acpi/acpica/nsrepair.c
@@ -45,13 +45,52 @@
45#include "accommon.h" 45#include "accommon.h"
46#include "acnamesp.h" 46#include "acnamesp.h"
47#include "acinterp.h" 47#include "acinterp.h"
48#include "acpredef.h"
49 48
50#define _COMPONENT ACPI_NAMESPACE 49#define _COMPONENT ACPI_NAMESPACE
51ACPI_MODULE_NAME("nsrepair") 50ACPI_MODULE_NAME("nsrepair")
52 51
53/******************************************************************************* 52/*******************************************************************************
54 * 53 *
54 * This module attempts to repair or convert objects returned by the
55 * predefined methods to an object type that is expected, as per the ACPI
56 * specification. The need for this code is dictated by the many machines that
57 * return incorrect types for the standard predefined methods. Performing these
58 * conversions here, in one place, eliminates the need for individual ACPI
59 * device drivers to do the same. Note: Most of these conversions are different
60 * than the internal object conversion routines used for implicit object
61 * conversion.
62 *
63 * The following conversions can be performed as necessary:
64 *
65 * Integer -> String
66 * Integer -> Buffer
67 * String -> Integer
68 * String -> Buffer
69 * Buffer -> Integer
70 * Buffer -> String
71 * Buffer -> Package of Integers
72 * Package -> Package of one Package
73 *
74 ******************************************************************************/
75/* Local prototypes */
76static acpi_status
77acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
78 union acpi_operand_object **return_object);
79
80static acpi_status
81acpi_ns_convert_to_string(union acpi_operand_object *original_object,
82 union acpi_operand_object **return_object);
83
84static acpi_status
85acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
86 union acpi_operand_object **return_object);
87
88static acpi_status
89acpi_ns_convert_to_package(union acpi_operand_object *original_object,
90 union acpi_operand_object **return_object);
91
92/*******************************************************************************
93 *
55 * FUNCTION: acpi_ns_repair_object 94 * FUNCTION: acpi_ns_repair_object
56 * 95 *
57 * PARAMETERS: Data - Pointer to validation data structure 96 * PARAMETERS: Data - Pointer to validation data structure
@@ -68,6 +107,7 @@ ACPI_MODULE_NAME("nsrepair")
68 * not expected. 107 * not expected.
69 * 108 *
70 ******************************************************************************/ 109 ******************************************************************************/
110
71acpi_status 111acpi_status
72acpi_ns_repair_object(struct acpi_predefined_data *data, 112acpi_ns_repair_object(struct acpi_predefined_data *data,
73 u32 expected_btypes, 113 u32 expected_btypes,
@@ -76,32 +116,206 @@ acpi_ns_repair_object(struct acpi_predefined_data *data,
76{ 116{
77 union acpi_operand_object *return_object = *return_object_ptr; 117 union acpi_operand_object *return_object = *return_object_ptr;
78 union acpi_operand_object *new_object; 118 union acpi_operand_object *new_object;
79 acpi_size length;
80 acpi_status status; 119 acpi_status status;
81 120
121 ACPI_FUNCTION_NAME(ns_repair_object);
122
82 /* 123 /*
83 * At this point, we know that the type of the returned object was not 124 * At this point, we know that the type of the returned object was not
84 * one of the expected types for this predefined name. Attempt to 125 * one of the expected types for this predefined name. Attempt to
85 * repair the object. Only a limited number of repairs are possible. 126 * repair the object by converting it to one of the expected object
127 * types for this predefined name.
86 */ 128 */
87 switch (return_object->common.type) { 129 if (expected_btypes & ACPI_RTYPE_INTEGER) {
130 status = acpi_ns_convert_to_integer(return_object, &new_object);
131 if (ACPI_SUCCESS(status)) {
132 goto object_repaired;
133 }
134 }
135 if (expected_btypes & ACPI_RTYPE_STRING) {
136 status = acpi_ns_convert_to_string(return_object, &new_object);
137 if (ACPI_SUCCESS(status)) {
138 goto object_repaired;
139 }
140 }
141 if (expected_btypes & ACPI_RTYPE_BUFFER) {
142 status = acpi_ns_convert_to_buffer(return_object, &new_object);
143 if (ACPI_SUCCESS(status)) {
144 goto object_repaired;
145 }
146 }
147 if (expected_btypes & ACPI_RTYPE_PACKAGE) {
148 status = acpi_ns_convert_to_package(return_object, &new_object);
149 if (ACPI_SUCCESS(status)) {
150 goto object_repaired;
151 }
152 }
153
154 /* We cannot repair this object */
155
156 return (AE_AML_OPERAND_TYPE);
157
158 object_repaired:
159
160 /* Object was successfully repaired */
161
162 /*
163 * If the original object is a package element, we need to:
164 * 1. Set the reference count of the new object to match the
165 * reference count of the old object.
166 * 2. Decrement the reference count of the original object.
167 */
168 if (package_index != ACPI_NOT_PACKAGE_ELEMENT) {
169 new_object->common.reference_count =
170 return_object->common.reference_count;
171
172 if (return_object->common.reference_count > 1) {
173 return_object->common.reference_count--;
174 }
175
176 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
177 "%s: Converted %s to expected %s at index %u\n",
178 data->pathname,
179 acpi_ut_get_object_type_name(return_object),
180 acpi_ut_get_object_type_name(new_object),
181 package_index));
182 } else {
183 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
184 "%s: Converted %s to expected %s\n",
185 data->pathname,
186 acpi_ut_get_object_type_name(return_object),
187 acpi_ut_get_object_type_name(new_object)));
188 }
189
190 /* Delete old object, install the new return object */
191
192 acpi_ut_remove_reference(return_object);
193 *return_object_ptr = new_object;
194 data->flags |= ACPI_OBJECT_REPAIRED;
195 return (AE_OK);
196}
197
198/*******************************************************************************
199 *
200 * FUNCTION: acpi_ns_convert_to_integer
201 *
202 * PARAMETERS: original_object - Object to be converted
203 * return_object - Where the new converted object is returned
204 *
205 * RETURN: Status. AE_OK if conversion was successful.
206 *
207 * DESCRIPTION: Attempt to convert a String/Buffer object to an Integer.
208 *
209 ******************************************************************************/
210
211static acpi_status
212acpi_ns_convert_to_integer(union acpi_operand_object *original_object,
213 union acpi_operand_object **return_object)
214{
215 union acpi_operand_object *new_object;
216 acpi_status status;
217 u64 value = 0;
218 u32 i;
219
220 switch (original_object->common.type) {
221 case ACPI_TYPE_STRING:
222
223 /* String-to-Integer conversion */
224
225 status = acpi_ut_strtoul64(original_object->string.pointer,
226 ACPI_ANY_BASE, &value);
227 if (ACPI_FAILURE(status)) {
228 return (status);
229 }
230 break;
231
88 case ACPI_TYPE_BUFFER: 232 case ACPI_TYPE_BUFFER:
89 233
90 /* Does the method/object legally return a string? */ 234 /* Buffer-to-Integer conversion. Max buffer size is 64 bits. */
91 235
92 if (!(expected_btypes & ACPI_RTYPE_STRING)) { 236 if (original_object->buffer.length > 8) {
93 return (AE_AML_OPERAND_TYPE); 237 return (AE_AML_OPERAND_TYPE);
94 } 238 }
95 239
240 /* Extract each buffer byte to create the integer */
241
242 for (i = 0; i < original_object->buffer.length; i++) {
243 value |=
244 ((u64) original_object->buffer.
245 pointer[i] << (i * 8));
246 }
247 break;
248
249 default:
250 return (AE_AML_OPERAND_TYPE);
251 }
252
253 new_object = acpi_ut_create_integer_object(value);
254 if (!new_object) {
255 return (AE_NO_MEMORY);
256 }
257
258 *return_object = new_object;
259 return (AE_OK);
260}
261
262/*******************************************************************************
263 *
264 * FUNCTION: acpi_ns_convert_to_string
265 *
266 * PARAMETERS: original_object - Object to be converted
267 * return_object - Where the new converted object is returned
268 *
269 * RETURN: Status. AE_OK if conversion was successful.
270 *
271 * DESCRIPTION: Attempt to convert a Integer/Buffer object to a String.
272 *
273 ******************************************************************************/
274
275static acpi_status
276acpi_ns_convert_to_string(union acpi_operand_object *original_object,
277 union acpi_operand_object **return_object)
278{
279 union acpi_operand_object *new_object;
280 acpi_size length;
281 acpi_status status;
282
283 switch (original_object->common.type) {
284 case ACPI_TYPE_INTEGER:
285 /*
286 * Integer-to-String conversion. Commonly, convert
287 * an integer of value 0 to a NULL string. The last element of
288 * _BIF and _BIX packages occasionally need this fix.
289 */
290 if (original_object->integer.value == 0) {
291
292 /* Allocate a new NULL string object */
293
294 new_object = acpi_ut_create_string_object(0);
295 if (!new_object) {
296 return (AE_NO_MEMORY);
297 }
298 } else {
299 status =
300 acpi_ex_convert_to_string(original_object,
301 &new_object,
302 ACPI_IMPLICIT_CONVERT_HEX);
303 if (ACPI_FAILURE(status)) {
304 return (status);
305 }
306 }
307 break;
308
309 case ACPI_TYPE_BUFFER:
96 /* 310 /*
97 * Have a Buffer, expected a String, convert. Use a to_string 311 * Buffer-to-String conversion. Use a to_string
98 * conversion, no transform performed on the buffer data. The best 312 * conversion, no transform performed on the buffer data. The best
99 * example of this is the _BIF method, where the string data from 313 * example of this is the _BIF method, where the string data from
100 * the battery is often (incorrectly) returned as buffer object(s). 314 * the battery is often (incorrectly) returned as buffer object(s).
101 */ 315 */
102 length = 0; 316 length = 0;
103 while ((length < return_object->buffer.length) && 317 while ((length < original_object->buffer.length) &&
104 (return_object->buffer.pointer[length])) { 318 (original_object->buffer.pointer[length])) {
105 length++; 319 length++;
106 } 320 }
107 321
@@ -117,94 +331,176 @@ acpi_ns_repair_object(struct acpi_predefined_data *data,
117 * terminated at Length+1. 331 * terminated at Length+1.
118 */ 332 */
119 ACPI_MEMCPY(new_object->string.pointer, 333 ACPI_MEMCPY(new_object->string.pointer,
120 return_object->buffer.pointer, length); 334 original_object->buffer.pointer, length);
121 break; 335 break;
122 336
337 default:
338 return (AE_AML_OPERAND_TYPE);
339 }
340
341 *return_object = new_object;
342 return (AE_OK);
343}
344
345/*******************************************************************************
346 *
347 * FUNCTION: acpi_ns_convert_to_buffer
348 *
349 * PARAMETERS: original_object - Object to be converted
350 * return_object - Where the new converted object is returned
351 *
352 * RETURN: Status. AE_OK if conversion was successful.
353 *
354 * DESCRIPTION: Attempt to convert a Integer/String/Package object to a Buffer.
355 *
356 ******************************************************************************/
357
358static acpi_status
359acpi_ns_convert_to_buffer(union acpi_operand_object *original_object,
360 union acpi_operand_object **return_object)
361{
362 union acpi_operand_object *new_object;
363 acpi_status status;
364 union acpi_operand_object **elements;
365 u32 *dword_buffer;
366 u32 count;
367 u32 i;
368
369 switch (original_object->common.type) {
123 case ACPI_TYPE_INTEGER: 370 case ACPI_TYPE_INTEGER:
371 /*
372 * Integer-to-Buffer conversion.
373 * Convert the Integer to a packed-byte buffer. _MAT and other
374 * objects need this sometimes, if a read has been performed on a
375 * Field object that is less than or equal to the global integer
376 * size (32 or 64 bits).
377 */
378 status =
379 acpi_ex_convert_to_buffer(original_object, &new_object);
380 if (ACPI_FAILURE(status)) {
381 return (status);
382 }
383 break;
124 384
125 /* 1) Does the method/object legally return a buffer? */ 385 case ACPI_TYPE_STRING:
126 386
127 if (expected_btypes & ACPI_RTYPE_BUFFER) { 387 /* String-to-Buffer conversion. Simple data copy */
128 /* 388
129 * Convert the Integer to a packed-byte buffer. _MAT needs 389 new_object =
130 * this sometimes, if a read has been performed on a Field 390 acpi_ut_create_buffer_object(original_object->string.
131 * object that is less than or equal to the global integer 391 length);
132 * size (32 or 64 bits). 392 if (!new_object) {
133 */ 393 return (AE_NO_MEMORY);
134 status =
135 acpi_ex_convert_to_buffer(return_object,
136 &new_object);
137 if (ACPI_FAILURE(status)) {
138 return (status);
139 }
140 } 394 }
141 395
142 /* 2) Does the method/object legally return a string? */ 396 ACPI_MEMCPY(new_object->buffer.pointer,
397 original_object->string.pointer,
398 original_object->string.length);
399 break;
400
401 case ACPI_TYPE_PACKAGE:
402 /*
403 * This case is often seen for predefined names that must return a
404 * Buffer object with multiple DWORD integers within. For example,
405 * _FDE and _GTM. The Package can be converted to a Buffer.
406 */
407
408 /* All elements of the Package must be integers */
143 409
144 else if (expected_btypes & ACPI_RTYPE_STRING) { 410 elements = original_object->package.elements;
145 /* 411 count = original_object->package.count;
146 * The only supported Integer-to-String conversion is to convert 412
147 * an integer of value 0 to a NULL string. The last element of 413 for (i = 0; i < count; i++) {
148 * _BIF and _BIX packages occasionally need this fix. 414 if ((!*elements) ||
149 */ 415 ((*elements)->common.type != ACPI_TYPE_INTEGER)) {
150 if (return_object->integer.value != 0) {
151 return (AE_AML_OPERAND_TYPE); 416 return (AE_AML_OPERAND_TYPE);
152 } 417 }
418 elements++;
419 }
153 420
154 /* Allocate a new NULL string object */ 421 /* Create the new buffer object to replace the Package */
155 422
156 new_object = acpi_ut_create_string_object(0); 423 new_object = acpi_ut_create_buffer_object(ACPI_MUL_4(count));
157 if (!new_object) { 424 if (!new_object) {
158 return (AE_NO_MEMORY); 425 return (AE_NO_MEMORY);
159 }
160 } else {
161 return (AE_AML_OPERAND_TYPE);
162 } 426 }
163 break;
164 427
165 default: 428 /* Copy the package elements (integers) to the buffer as DWORDs */
166 429
167 /* We cannot repair this object */ 430 elements = original_object->package.elements;
431 dword_buffer = ACPI_CAST_PTR(u32, new_object->buffer.pointer);
432
433 for (i = 0; i < count; i++) {
434 *dword_buffer = (u32) (*elements)->integer.value;
435 dword_buffer++;
436 elements++;
437 }
438 break;
168 439
440 default:
169 return (AE_AML_OPERAND_TYPE); 441 return (AE_AML_OPERAND_TYPE);
170 } 442 }
171 443
172 /* Object was successfully repaired */ 444 *return_object = new_object;
445 return (AE_OK);
446}
173 447
174 /* 448/*******************************************************************************
175 * If the original object is a package element, we need to: 449 *
176 * 1. Set the reference count of the new object to match the 450 * FUNCTION: acpi_ns_convert_to_package
177 * reference count of the old object. 451 *
178 * 2. Decrement the reference count of the original object. 452 * PARAMETERS: original_object - Object to be converted
179 */ 453 * return_object - Where the new converted object is returned
180 if (package_index != ACPI_NOT_PACKAGE_ELEMENT) { 454 *
181 new_object->common.reference_count = 455 * RETURN: Status. AE_OK if conversion was successful.
182 return_object->common.reference_count; 456 *
457 * DESCRIPTION: Attempt to convert a Buffer object to a Package. Each byte of
458 * the buffer is converted to a single integer package element.
459 *
460 ******************************************************************************/
183 461
184 if (return_object->common.reference_count > 1) { 462static acpi_status
185 return_object->common.reference_count--; 463acpi_ns_convert_to_package(union acpi_operand_object *original_object,
464 union acpi_operand_object **return_object)
465{
466 union acpi_operand_object *new_object;
467 union acpi_operand_object **elements;
468 u32 length;
469 u8 *buffer;
470
471 switch (original_object->common.type) {
472 case ACPI_TYPE_BUFFER:
473
474 /* Buffer-to-Package conversion */
475
476 length = original_object->buffer.length;
477 new_object = acpi_ut_create_package_object(length);
478 if (!new_object) {
479 return (AE_NO_MEMORY);
186 } 480 }
187 481
188 ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags, 482 /* Convert each buffer byte to an integer package element */
189 "Converted %s to expected %s at index %u",
190 acpi_ut_get_object_type_name
191 (return_object),
192 acpi_ut_get_object_type_name(new_object),
193 package_index));
194 } else {
195 ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
196 "Converted %s to expected %s",
197 acpi_ut_get_object_type_name
198 (return_object),
199 acpi_ut_get_object_type_name
200 (new_object)));
201 }
202 483
203 /* Delete old object, install the new return object */ 484 elements = new_object->package.elements;
485 buffer = original_object->buffer.pointer;
204 486
205 acpi_ut_remove_reference(return_object); 487 while (length--) {
206 *return_object_ptr = new_object; 488 *elements =
207 data->flags |= ACPI_OBJECT_REPAIRED; 489 acpi_ut_create_integer_object((u64) *buffer);
490 if (!*elements) {
491 acpi_ut_remove_reference(new_object);
492 return (AE_NO_MEMORY);
493 }
494 elements++;
495 buffer++;
496 }
497 break;
498
499 default:
500 return (AE_AML_OPERAND_TYPE);
501 }
502
503 *return_object = new_object;
208 return (AE_OK); 504 return (AE_OK);
209} 505}
210 506
@@ -238,6 +534,8 @@ acpi_ns_repair_package_list(struct acpi_predefined_data *data,
238{ 534{
239 union acpi_operand_object *pkg_obj_desc; 535 union acpi_operand_object *pkg_obj_desc;
240 536
537 ACPI_FUNCTION_NAME(ns_repair_package_list);
538
241 /* 539 /*
242 * Create the new outer package and populate it. The new package will 540 * Create the new outer package and populate it. The new package will
243 * have a single element, the lone subpackage. 541 * have a single element, the lone subpackage.
@@ -254,8 +552,9 @@ acpi_ns_repair_package_list(struct acpi_predefined_data *data,
254 *obj_desc_ptr = pkg_obj_desc; 552 *obj_desc_ptr = pkg_obj_desc;
255 data->flags |= ACPI_OBJECT_REPAIRED; 553 data->flags |= ACPI_OBJECT_REPAIRED;
256 554
257 ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags, 555 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
258 "Repaired Incorrectly formed Package")); 556 "%s: Repaired incorrectly formed Package\n",
557 data->pathname));
259 558
260 return (AE_OK); 559 return (AE_OK);
261} 560}
diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c
index d07b68613818..f13691c1cca5 100644
--- a/drivers/acpi/acpica/nsrepair2.c
+++ b/drivers/acpi/acpica/nsrepair2.c
@@ -45,6 +45,7 @@
45#include <acpi/acpi.h> 45#include <acpi/acpi.h>
46#include "accommon.h" 46#include "accommon.h"
47#include "acnamesp.h" 47#include "acnamesp.h"
48#include "acpredef.h"
48 49
49#define _COMPONENT ACPI_NAMESPACE 50#define _COMPONENT ACPI_NAMESPACE
50ACPI_MODULE_NAME("nsrepair2") 51ACPI_MODULE_NAME("nsrepair2")
@@ -74,6 +75,10 @@ acpi_ns_repair_ALR(struct acpi_predefined_data *data,
74 union acpi_operand_object **return_object_ptr); 75 union acpi_operand_object **return_object_ptr);
75 76
76static acpi_status 77static acpi_status
78acpi_ns_repair_FDE(struct acpi_predefined_data *data,
79 union acpi_operand_object **return_object_ptr);
80
81static acpi_status
77acpi_ns_repair_PSS(struct acpi_predefined_data *data, 82acpi_ns_repair_PSS(struct acpi_predefined_data *data,
78 union acpi_operand_object **return_object_ptr); 83 union acpi_operand_object **return_object_ptr);
79 84
@@ -89,9 +94,6 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data,
89 u8 sort_direction, char *sort_key_name); 94 u8 sort_direction, char *sort_key_name);
90 95
91static acpi_status 96static acpi_status
92acpi_ns_remove_null_elements(union acpi_operand_object *package);
93
94static acpi_status
95acpi_ns_sort_list(union acpi_operand_object **elements, 97acpi_ns_sort_list(union acpi_operand_object **elements,
96 u32 count, u32 index, u8 sort_direction); 98 u32 count, u32 index, u8 sort_direction);
97 99
@@ -104,17 +106,27 @@ acpi_ns_sort_list(union acpi_operand_object **elements,
104 * This table contains the names of the predefined methods for which we can 106 * This table contains the names of the predefined methods for which we can
105 * perform more complex repairs. 107 * perform more complex repairs.
106 * 108 *
107 * _ALR: Sort the list ascending by ambient_illuminance if necessary 109 * As necessary:
108 * _PSS: Sort the list descending by Power if necessary 110 *
109 * _TSS: Sort the list descending by Power if necessary 111 * _ALR: Sort the list ascending by ambient_illuminance
112 * _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs
113 * _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs
114 * _PSS: Sort the list descending by Power
115 * _TSS: Sort the list descending by Power
110 */ 116 */
111static const struct acpi_repair_info acpi_ns_repairable_names[] = { 117static const struct acpi_repair_info acpi_ns_repairable_names[] = {
112 {"_ALR", acpi_ns_repair_ALR}, 118 {"_ALR", acpi_ns_repair_ALR},
119 {"_FDE", acpi_ns_repair_FDE},
120 {"_GTM", acpi_ns_repair_FDE}, /* _GTM has same repair as _FDE */
113 {"_PSS", acpi_ns_repair_PSS}, 121 {"_PSS", acpi_ns_repair_PSS},
114 {"_TSS", acpi_ns_repair_TSS}, 122 {"_TSS", acpi_ns_repair_TSS},
115 {{0, 0, 0, 0}, NULL} /* Table terminator */ 123 {{0, 0, 0, 0}, NULL} /* Table terminator */
116}; 124};
117 125
126#define ACPI_FDE_FIELD_COUNT 5
127#define ACPI_FDE_BYTE_BUFFER_SIZE 5
128#define ACPI_FDE_DWORD_BUFFER_SIZE (ACPI_FDE_FIELD_COUNT * sizeof (u32))
129
118/****************************************************************************** 130/******************************************************************************
119 * 131 *
120 * FUNCTION: acpi_ns_complex_repairs 132 * FUNCTION: acpi_ns_complex_repairs
@@ -215,6 +227,94 @@ acpi_ns_repair_ALR(struct acpi_predefined_data *data,
215 227
216/****************************************************************************** 228/******************************************************************************
217 * 229 *
230 * FUNCTION: acpi_ns_repair_FDE
231 *
232 * PARAMETERS: Data - Pointer to validation data structure
233 * return_object_ptr - Pointer to the object returned from the
234 * evaluation of a method or object
235 *
236 * RETURN: Status. AE_OK if object is OK or was repaired successfully
237 *
238 * DESCRIPTION: Repair for the _FDE and _GTM objects. The expected return
239 * value is a Buffer of 5 DWORDs. This function repairs a common
240 * problem where the return value is a Buffer of BYTEs, not
241 * DWORDs.
242 *
243 *****************************************************************************/
244
245static acpi_status
246acpi_ns_repair_FDE(struct acpi_predefined_data *data,
247 union acpi_operand_object **return_object_ptr)
248{
249 union acpi_operand_object *return_object = *return_object_ptr;
250 union acpi_operand_object *buffer_object;
251 u8 *byte_buffer;
252 u32 *dword_buffer;
253 u32 i;
254
255 ACPI_FUNCTION_NAME(ns_repair_FDE);
256
257 switch (return_object->common.type) {
258 case ACPI_TYPE_BUFFER:
259
260 /* This is the expected type. Length should be (at least) 5 DWORDs */
261
262 if (return_object->buffer.length >= ACPI_FDE_DWORD_BUFFER_SIZE) {
263 return (AE_OK);
264 }
265
266 /* We can only repair if we have exactly 5 BYTEs */
267
268 if (return_object->buffer.length != ACPI_FDE_BYTE_BUFFER_SIZE) {
269 ACPI_WARN_PREDEFINED((AE_INFO, data->pathname,
270 data->node_flags,
271 "Incorrect return buffer length %u, expected %u",
272 return_object->buffer.length,
273 ACPI_FDE_DWORD_BUFFER_SIZE));
274
275 return (AE_AML_OPERAND_TYPE);
276 }
277
278 /* Create the new (larger) buffer object */
279
280 buffer_object =
281 acpi_ut_create_buffer_object(ACPI_FDE_DWORD_BUFFER_SIZE);
282 if (!buffer_object) {
283 return (AE_NO_MEMORY);
284 }
285
286 /* Expand each byte to a DWORD */
287
288 byte_buffer = return_object->buffer.pointer;
289 dword_buffer =
290 ACPI_CAST_PTR(u32, buffer_object->buffer.pointer);
291
292 for (i = 0; i < ACPI_FDE_FIELD_COUNT; i++) {
293 *dword_buffer = (u32) *byte_buffer;
294 dword_buffer++;
295 byte_buffer++;
296 }
297
298 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
299 "%s Expanded Byte Buffer to expected DWord Buffer\n",
300 data->pathname));
301 break;
302
303 default:
304 return (AE_AML_OPERAND_TYPE);
305 }
306
307 /* Delete the original return object, return the new buffer object */
308
309 acpi_ut_remove_reference(return_object);
310 *return_object_ptr = buffer_object;
311
312 data->flags |= ACPI_OBJECT_REPAIRED;
313 return (AE_OK);
314}
315
316/******************************************************************************
317 *
218 * FUNCTION: acpi_ns_repair_TSS 318 * FUNCTION: acpi_ns_repair_TSS
219 * 319 *
220 * PARAMETERS: Data - Pointer to validation data structure 320 * PARAMETERS: Data - Pointer to validation data structure
@@ -345,6 +445,8 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data,
345 u32 previous_value; 445 u32 previous_value;
346 acpi_status status; 446 acpi_status status;
347 447
448 ACPI_FUNCTION_NAME(ns_check_sorted_list);
449
348 /* The top-level object must be a package */ 450 /* The top-level object must be a package */
349 451
350 if (return_object->common.type != ACPI_TYPE_PACKAGE) { 452 if (return_object->common.type != ACPI_TYPE_PACKAGE) {
@@ -352,24 +454,10 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data,
352 } 454 }
353 455
354 /* 456 /*
355 * Detect any NULL package elements and remove them from the 457 * NOTE: assumes list of sub-packages contains no NULL elements.
356 * package. 458 * Any NULL elements should have been removed by earlier call
357 * 459 * to acpi_ns_remove_null_elements.
358 * TBD: We may want to do this for all predefined names that
359 * return a variable-length package of packages.
360 */ 460 */
361 status = acpi_ns_remove_null_elements(return_object);
362 if (status == AE_NULL_ENTRY) {
363 ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
364 "NULL elements removed from package"));
365
366 /* Exit if package is now zero length */
367
368 if (!return_object->package.count) {
369 return (AE_NULL_ENTRY);
370 }
371 }
372
373 outer_elements = return_object->package.elements; 461 outer_elements = return_object->package.elements;
374 outer_element_count = return_object->package.count; 462 outer_element_count = return_object->package.count;
375 if (!outer_element_count) { 463 if (!outer_element_count) {
@@ -422,10 +510,9 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data,
422 510
423 data->flags |= ACPI_OBJECT_REPAIRED; 511 data->flags |= ACPI_OBJECT_REPAIRED;
424 512
425 ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, 513 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
426 data->node_flags, 514 "%s: Repaired unsorted list - now sorted by %s\n",
427 "Repaired unsorted list - now sorted by %s", 515 data->pathname, sort_key_name));
428 sort_key_name));
429 return (AE_OK); 516 return (AE_OK);
430 } 517 }
431 518
@@ -440,36 +527,63 @@ acpi_ns_check_sorted_list(struct acpi_predefined_data *data,
440 * 527 *
441 * FUNCTION: acpi_ns_remove_null_elements 528 * FUNCTION: acpi_ns_remove_null_elements
442 * 529 *
443 * PARAMETERS: obj_desc - A Package object 530 * PARAMETERS: Data - Pointer to validation data structure
531 * package_type - An acpi_return_package_types value
532 * obj_desc - A Package object
444 * 533 *
445 * RETURN: Status. AE_NULL_ENTRY means that one or more elements were 534 * RETURN: None.
446 * removed.
447 * 535 *
448 * DESCRIPTION: Remove all NULL package elements and update the package count. 536 * DESCRIPTION: Remove all NULL package elements from packages that contain
537 * a variable number of sub-packages.
449 * 538 *
450 *****************************************************************************/ 539 *****************************************************************************/
451 540
452static acpi_status 541void
453acpi_ns_remove_null_elements(union acpi_operand_object *obj_desc) 542acpi_ns_remove_null_elements(struct acpi_predefined_data *data,
543 u8 package_type,
544 union acpi_operand_object *obj_desc)
454{ 545{
455 union acpi_operand_object **source; 546 union acpi_operand_object **source;
456 union acpi_operand_object **dest; 547 union acpi_operand_object **dest;
457 acpi_status status = AE_OK;
458 u32 count; 548 u32 count;
459 u32 new_count; 549 u32 new_count;
460 u32 i; 550 u32 i;
461 551
552 ACPI_FUNCTION_NAME(ns_remove_null_elements);
553
554 /*
555 * PTYPE1 packages contain no subpackages.
556 * PTYPE2 packages contain a variable number of sub-packages. We can
557 * safely remove all NULL elements from the PTYPE2 packages.
558 */
559 switch (package_type) {
560 case ACPI_PTYPE1_FIXED:
561 case ACPI_PTYPE1_VAR:
562 case ACPI_PTYPE1_OPTION:
563 return;
564
565 case ACPI_PTYPE2:
566 case ACPI_PTYPE2_COUNT:
567 case ACPI_PTYPE2_PKG_COUNT:
568 case ACPI_PTYPE2_FIXED:
569 case ACPI_PTYPE2_MIN:
570 case ACPI_PTYPE2_REV_FIXED:
571 break;
572
573 default:
574 return;
575 }
576
462 count = obj_desc->package.count; 577 count = obj_desc->package.count;
463 new_count = count; 578 new_count = count;
464 579
465 source = obj_desc->package.elements; 580 source = obj_desc->package.elements;
466 dest = source; 581 dest = source;
467 582
468 /* Examine all elements of the package object */ 583 /* Examine all elements of the package object, remove nulls */
469 584
470 for (i = 0; i < count; i++) { 585 for (i = 0; i < count; i++) {
471 if (!*source) { 586 if (!*source) {
472 status = AE_NULL_ENTRY;
473 new_count--; 587 new_count--;
474 } else { 588 } else {
475 *dest = *source; 589 *dest = *source;
@@ -478,15 +592,18 @@ acpi_ns_remove_null_elements(union acpi_operand_object *obj_desc)
478 source++; 592 source++;
479 } 593 }
480 594
481 if (status == AE_NULL_ENTRY) { 595 /* Update parent package if any null elements were removed */
596
597 if (new_count < count) {
598 ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
599 "%s: Found and removed %u NULL elements\n",
600 data->pathname, (count - new_count)));
482 601
483 /* NULL terminate list and update the package count */ 602 /* NULL terminate list and update the package count */
484 603
485 *dest = NULL; 604 *dest = NULL;
486 obj_desc->package.count = new_count; 605 obj_desc->package.count = new_count;
487 } 606 }
488
489 return (status);
490} 607}
491 608
492/****************************************************************************** 609/******************************************************************************
diff --git a/drivers/acpi/acpica/nsutils.c b/drivers/acpi/acpica/nsutils.c
index ea55ab4f9849..47d91e668a1b 100644
--- a/drivers/acpi/acpica/nsutils.c
+++ b/drivers/acpi/acpica/nsutils.c
@@ -671,24 +671,25 @@ acpi_ns_externalize_name(u32 internal_name_length,
671 671
672/******************************************************************************* 672/*******************************************************************************
673 * 673 *
674 * FUNCTION: acpi_ns_map_handle_to_node 674 * FUNCTION: acpi_ns_validate_handle
675 * 675 *
676 * PARAMETERS: Handle - Handle to be converted to an Node 676 * PARAMETERS: Handle - Handle to be validated and typecast to a
677 * namespace node.
677 * 678 *
678 * RETURN: A Name table entry pointer 679 * RETURN: A pointer to a namespace node
679 * 680 *
680 * DESCRIPTION: Convert a namespace handle to a real Node 681 * DESCRIPTION: Convert a namespace handle to a namespace node. Handles special
682 * cases for the root node.
681 * 683 *
682 * Note: Real integer handles would allow for more verification 684 * NOTE: Real integer handles would allow for more verification
683 * and keep all pointers within this subsystem - however this introduces 685 * and keep all pointers within this subsystem - however this introduces
684 * more (and perhaps unnecessary) overhead. 686 * more overhead and has not been necessary to this point. Drivers
685 * 687 * holding handles are typically notified before a node becomes invalid
686 * The current implemenation is basically a placeholder until such time comes 688 * due to a table unload.
687 * that it is needed.
688 * 689 *
689 ******************************************************************************/ 690 ******************************************************************************/
690 691
691struct acpi_namespace_node *acpi_ns_map_handle_to_node(acpi_handle handle) 692struct acpi_namespace_node *acpi_ns_validate_handle(acpi_handle handle)
692{ 693{
693 694
694 ACPI_FUNCTION_ENTRY(); 695 ACPI_FUNCTION_ENTRY();
@@ -710,42 +711,6 @@ struct acpi_namespace_node *acpi_ns_map_handle_to_node(acpi_handle handle)
710 711
711/******************************************************************************* 712/*******************************************************************************
712 * 713 *
713 * FUNCTION: acpi_ns_convert_entry_to_handle
714 *
715 * PARAMETERS: Node - Node to be converted to a Handle
716 *
717 * RETURN: A user handle
718 *
719 * DESCRIPTION: Convert a real Node to a namespace handle
720 *
721 ******************************************************************************/
722
723acpi_handle acpi_ns_convert_entry_to_handle(struct acpi_namespace_node *node)
724{
725
726 /*
727 * Simple implementation for now;
728 */
729 return ((acpi_handle) node);
730
731/* Example future implementation ---------------------
732
733 if (!Node)
734 {
735 return (NULL);
736 }
737
738 if (Node == acpi_gbl_root_node)
739 {
740 return (ACPI_ROOT_OBJECT);
741 }
742
743 return ((acpi_handle) Node);
744------------------------------------------------------*/
745}
746
747/*******************************************************************************
748 *
749 * FUNCTION: acpi_ns_terminate 714 * FUNCTION: acpi_ns_terminate
750 * 715 *
751 * PARAMETERS: none 716 * PARAMETERS: none
diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c
index f2bd1da77001..f0c0892bc7e5 100644
--- a/drivers/acpi/acpica/nsxfeval.c
+++ b/drivers/acpi/acpica/nsxfeval.c
@@ -190,7 +190,7 @@ acpi_evaluate_object(acpi_handle handle,
190 190
191 /* Convert and validate the device handle */ 191 /* Convert and validate the device handle */
192 192
193 info->prefix_node = acpi_ns_map_handle_to_node(handle); 193 info->prefix_node = acpi_ns_validate_handle(handle);
194 if (!info->prefix_node) { 194 if (!info->prefix_node) {
195 status = AE_BAD_PARAMETER; 195 status = AE_BAD_PARAMETER;
196 goto cleanup; 196 goto cleanup;
@@ -552,7 +552,7 @@ acpi_ns_get_device_callback(acpi_handle obj_handle,
552 return (status); 552 return (status);
553 } 553 }
554 554
555 node = acpi_ns_map_handle_to_node(obj_handle); 555 node = acpi_ns_validate_handle(obj_handle);
556 status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 556 status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
557 if (ACPI_FAILURE(status)) { 557 if (ACPI_FAILURE(status)) {
558 return (status); 558 return (status);
@@ -729,7 +729,7 @@ acpi_attach_data(acpi_handle obj_handle,
729 729
730 /* Convert and validate the handle */ 730 /* Convert and validate the handle */
731 731
732 node = acpi_ns_map_handle_to_node(obj_handle); 732 node = acpi_ns_validate_handle(obj_handle);
733 if (!node) { 733 if (!node) {
734 status = AE_BAD_PARAMETER; 734 status = AE_BAD_PARAMETER;
735 goto unlock_and_exit; 735 goto unlock_and_exit;
@@ -775,7 +775,7 @@ acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler)
775 775
776 /* Convert and validate the handle */ 776 /* Convert and validate the handle */
777 777
778 node = acpi_ns_map_handle_to_node(obj_handle); 778 node = acpi_ns_validate_handle(obj_handle);
779 if (!node) { 779 if (!node) {
780 status = AE_BAD_PARAMETER; 780 status = AE_BAD_PARAMETER;
781 goto unlock_and_exit; 781 goto unlock_and_exit;
@@ -822,7 +822,7 @@ acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data)
822 822
823 /* Convert and validate the handle */ 823 /* Convert and validate the handle */
824 824
825 node = acpi_ns_map_handle_to_node(obj_handle); 825 node = acpi_ns_validate_handle(obj_handle);
826 if (!node) { 826 if (!node) {
827 status = AE_BAD_PARAMETER; 827 status = AE_BAD_PARAMETER;
828 goto unlock_and_exit; 828 goto unlock_and_exit;
diff --git a/drivers/acpi/acpica/nsxfname.c b/drivers/acpi/acpica/nsxfname.c
index ddc84af6336e..e611dd961b20 100644
--- a/drivers/acpi/acpica/nsxfname.c
+++ b/drivers/acpi/acpica/nsxfname.c
@@ -93,7 +93,7 @@ acpi_get_handle(acpi_handle parent,
93 /* Convert a parent handle to a prefix node */ 93 /* Convert a parent handle to a prefix node */
94 94
95 if (parent) { 95 if (parent) {
96 prefix_node = acpi_ns_map_handle_to_node(parent); 96 prefix_node = acpi_ns_validate_handle(parent);
97 if (!prefix_node) { 97 if (!prefix_node) {
98 return (AE_BAD_PARAMETER); 98 return (AE_BAD_PARAMETER);
99 } 99 }
@@ -114,7 +114,7 @@ acpi_get_handle(acpi_handle parent,
114 114
115 if (!ACPI_STRCMP(pathname, ACPI_NS_ROOT_PATH)) { 115 if (!ACPI_STRCMP(pathname, ACPI_NS_ROOT_PATH)) {
116 *ret_handle = 116 *ret_handle =
117 acpi_ns_convert_entry_to_handle(acpi_gbl_root_node); 117 ACPI_CAST_PTR(acpi_handle, acpi_gbl_root_node);
118 return (AE_OK); 118 return (AE_OK);
119 } 119 }
120 } else if (!prefix_node) { 120 } else if (!prefix_node) {
@@ -129,7 +129,7 @@ acpi_get_handle(acpi_handle parent,
129 status = 129 status =
130 acpi_ns_get_node(prefix_node, pathname, ACPI_NS_NO_UPSEARCH, &node); 130 acpi_ns_get_node(prefix_node, pathname, ACPI_NS_NO_UPSEARCH, &node);
131 if (ACPI_SUCCESS(status)) { 131 if (ACPI_SUCCESS(status)) {
132 *ret_handle = acpi_ns_convert_entry_to_handle(node); 132 *ret_handle = ACPI_CAST_PTR(acpi_handle, node);
133 } 133 }
134 134
135 return (status); 135 return (status);
@@ -186,7 +186,7 @@ acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer)
186 return (status); 186 return (status);
187 } 187 }
188 188
189 node = acpi_ns_map_handle_to_node(handle); 189 node = acpi_ns_validate_handle(handle);
190 if (!node) { 190 if (!node) {
191 status = AE_BAD_PARAMETER; 191 status = AE_BAD_PARAMETER;
192 goto unlock_and_exit; 192 goto unlock_and_exit;
@@ -291,7 +291,7 @@ acpi_get_object_info(acpi_handle handle,
291 goto cleanup; 291 goto cleanup;
292 } 292 }
293 293
294 node = acpi_ns_map_handle_to_node(handle); 294 node = acpi_ns_validate_handle(handle);
295 if (!node) { 295 if (!node) {
296 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 296 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
297 return (AE_BAD_PARAMETER); 297 return (AE_BAD_PARAMETER);
diff --git a/drivers/acpi/acpica/nsxfobj.c b/drivers/acpi/acpica/nsxfobj.c
index 4071bad4458e..0cc6ba01a495 100644
--- a/drivers/acpi/acpica/nsxfobj.c
+++ b/drivers/acpi/acpica/nsxfobj.c
@@ -79,7 +79,7 @@ acpi_status acpi_get_id(acpi_handle handle, acpi_owner_id * ret_id)
79 79
80 /* Convert and validate the handle */ 80 /* Convert and validate the handle */
81 81
82 node = acpi_ns_map_handle_to_node(handle); 82 node = acpi_ns_validate_handle(handle);
83 if (!node) { 83 if (!node) {
84 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 84 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
85 return (AE_BAD_PARAMETER); 85 return (AE_BAD_PARAMETER);
@@ -132,7 +132,7 @@ acpi_status acpi_get_type(acpi_handle handle, acpi_object_type * ret_type)
132 132
133 /* Convert and validate the handle */ 133 /* Convert and validate the handle */
134 134
135 node = acpi_ns_map_handle_to_node(handle); 135 node = acpi_ns_validate_handle(handle);
136 if (!node) { 136 if (!node) {
137 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 137 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
138 return (AE_BAD_PARAMETER); 138 return (AE_BAD_PARAMETER);
@@ -182,7 +182,7 @@ acpi_status acpi_get_parent(acpi_handle handle, acpi_handle * ret_handle)
182 182
183 /* Convert and validate the handle */ 183 /* Convert and validate the handle */
184 184
185 node = acpi_ns_map_handle_to_node(handle); 185 node = acpi_ns_validate_handle(handle);
186 if (!node) { 186 if (!node) {
187 status = AE_BAD_PARAMETER; 187 status = AE_BAD_PARAMETER;
188 goto unlock_and_exit; 188 goto unlock_and_exit;
@@ -191,7 +191,7 @@ acpi_status acpi_get_parent(acpi_handle handle, acpi_handle * ret_handle)
191 /* Get the parent entry */ 191 /* Get the parent entry */
192 192
193 parent_node = acpi_ns_get_parent_node(node); 193 parent_node = acpi_ns_get_parent_node(node);
194 *ret_handle = acpi_ns_convert_entry_to_handle(parent_node); 194 *ret_handle = ACPI_CAST_PTR(acpi_handle, parent_node);
195 195
196 /* Return exception if parent is null */ 196 /* Return exception if parent is null */
197 197
@@ -251,7 +251,7 @@ acpi_get_next_object(acpi_object_type type,
251 251
252 /* Start search at the beginning of the specified scope */ 252 /* Start search at the beginning of the specified scope */
253 253
254 parent_node = acpi_ns_map_handle_to_node(parent); 254 parent_node = acpi_ns_validate_handle(parent);
255 if (!parent_node) { 255 if (!parent_node) {
256 status = AE_BAD_PARAMETER; 256 status = AE_BAD_PARAMETER;
257 goto unlock_and_exit; 257 goto unlock_and_exit;
@@ -260,7 +260,7 @@ acpi_get_next_object(acpi_object_type type,
260 /* Non-null handle, ignore the parent */ 260 /* Non-null handle, ignore the parent */
261 /* Convert and validate the handle */ 261 /* Convert and validate the handle */
262 262
263 child_node = acpi_ns_map_handle_to_node(child); 263 child_node = acpi_ns_validate_handle(child);
264 if (!child_node) { 264 if (!child_node) {
265 status = AE_BAD_PARAMETER; 265 status = AE_BAD_PARAMETER;
266 goto unlock_and_exit; 266 goto unlock_and_exit;
@@ -276,7 +276,7 @@ acpi_get_next_object(acpi_object_type type,
276 } 276 }
277 277
278 if (ret_handle) { 278 if (ret_handle) {
279 *ret_handle = acpi_ns_convert_entry_to_handle(node); 279 *ret_handle = ACPI_CAST_PTR(acpi_handle, node);
280 } 280 }
281 281
282 unlock_and_exit: 282 unlock_and_exit:
diff --git a/drivers/acpi/acpica/psxface.c b/drivers/acpi/acpica/psxface.c
index 12934ad6da8e..d0c1b91eb8ca 100644
--- a/drivers/acpi/acpica/psxface.c
+++ b/drivers/acpi/acpica/psxface.c
@@ -287,7 +287,8 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info)
287 /* Invoke an internal method if necessary */ 287 /* Invoke an internal method if necessary */
288 288
289 if (info->obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { 289 if (info->obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) {
290 status = info->obj_desc->method.implementation(walk_state); 290 status =
291 info->obj_desc->method.extra.implementation(walk_state);
291 info->return_object = walk_state->return_desc; 292 info->return_object = walk_state->return_desc;
292 293
293 /* Cleanup states */ 294 /* Cleanup states */
diff --git a/drivers/acpi/acpica/rsxface.c b/drivers/acpi/acpica/rsxface.c
index 395212bcd19b..f27feb4772f6 100644
--- a/drivers/acpi/acpica/rsxface.c
+++ b/drivers/acpi/acpica/rsxface.c
@@ -104,7 +104,7 @@ acpi_rs_validate_parameters(acpi_handle device_handle,
104 return_ACPI_STATUS(AE_BAD_PARAMETER); 104 return_ACPI_STATUS(AE_BAD_PARAMETER);
105 } 105 }
106 106
107 node = acpi_ns_map_handle_to_node(device_handle); 107 node = acpi_ns_validate_handle(device_handle);
108 if (!node) { 108 if (!node) {
109 return_ACPI_STATUS(AE_BAD_PARAMETER); 109 return_ACPI_STATUS(AE_BAD_PARAMETER);
110 } 110 }
diff --git a/drivers/acpi/acpica/utcopy.c b/drivers/acpi/acpica/utcopy.c
index 0f0c64bf8ac9..f857c5efb79f 100644
--- a/drivers/acpi/acpica/utcopy.c
+++ b/drivers/acpi/acpica/utcopy.c
@@ -323,11 +323,11 @@ acpi_ut_copy_ielement_to_eelement(u8 object_type,
323 * RETURN: Status 323 * RETURN: Status
324 * 324 *
325 * DESCRIPTION: This function is called to place a package object in a user 325 * DESCRIPTION: This function is called to place a package object in a user
326 * buffer. A package object by definition contains other objects. 326 * buffer. A package object by definition contains other objects.
327 * 327 *
328 * The buffer is assumed to have sufficient space for the object. 328 * The buffer is assumed to have sufficient space for the object.
329 * The caller must have verified the buffer length needed using the 329 * The caller must have verified the buffer length needed using
330 * acpi_ut_get_object_size function before calling this function. 330 * the acpi_ut_get_object_size function before calling this function.
331 * 331 *
332 ******************************************************************************/ 332 ******************************************************************************/
333 333
@@ -382,12 +382,12 @@ acpi_ut_copy_ipackage_to_epackage(union acpi_operand_object *internal_object,
382 * FUNCTION: acpi_ut_copy_iobject_to_eobject 382 * FUNCTION: acpi_ut_copy_iobject_to_eobject
383 * 383 *
384 * PARAMETERS: internal_object - The internal object to be converted 384 * PARAMETERS: internal_object - The internal object to be converted
385 * buffer_ptr - Where the object is returned 385 * ret_buffer - Where the object is returned
386 * 386 *
387 * RETURN: Status 387 * RETURN: Status
388 * 388 *
389 * DESCRIPTION: This function is called to build an API object to be returned to 389 * DESCRIPTION: This function is called to build an API object to be returned
390 * the caller. 390 * to the caller.
391 * 391 *
392 ******************************************************************************/ 392 ******************************************************************************/
393 393
@@ -626,7 +626,7 @@ acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object,
626 * PARAMETERS: external_object - The external object to be converted 626 * PARAMETERS: external_object - The external object to be converted
627 * internal_object - Where the internal object is returned 627 * internal_object - Where the internal object is returned
628 * 628 *
629 * RETURN: Status - the status of the call 629 * RETURN: Status
630 * 630 *
631 * DESCRIPTION: Converts an external object to an internal object. 631 * DESCRIPTION: Converts an external object to an internal object.
632 * 632 *
@@ -665,7 +665,7 @@ acpi_ut_copy_eobject_to_iobject(union acpi_object *external_object,
665 * 665 *
666 * RETURN: Status 666 * RETURN: Status
667 * 667 *
668 * DESCRIPTION: Simple copy of one internal object to another. Reference count 668 * DESCRIPTION: Simple copy of one internal object to another. Reference count
669 * of the destination object is preserved. 669 * of the destination object is preserved.
670 * 670 *
671 ******************************************************************************/ 671 ******************************************************************************/
@@ -897,10 +897,11 @@ acpi_ut_copy_ielement_to_ielement(u8 object_type,
897 * 897 *
898 * FUNCTION: acpi_ut_copy_ipackage_to_ipackage 898 * FUNCTION: acpi_ut_copy_ipackage_to_ipackage
899 * 899 *
900 * PARAMETERS: *source_obj - Pointer to the source package object 900 * PARAMETERS: source_obj - Pointer to the source package object
901 * *dest_obj - Where the internal object is returned 901 * dest_obj - Where the internal object is returned
902 * walk_state - Current Walk state descriptor
902 * 903 *
903 * RETURN: Status - the status of the call 904 * RETURN: Status
904 * 905 *
905 * DESCRIPTION: This function is called to copy an internal package object 906 * DESCRIPTION: This function is called to copy an internal package object
906 * into another internal package object. 907 * into another internal package object.
@@ -953,9 +954,9 @@ acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj,
953 * 954 *
954 * FUNCTION: acpi_ut_copy_iobject_to_iobject 955 * FUNCTION: acpi_ut_copy_iobject_to_iobject
955 * 956 *
956 * PARAMETERS: walk_state - Current walk state 957 * PARAMETERS: source_desc - The internal object to be copied
957 * source_desc - The internal object to be copied
958 * dest_desc - Where the copied object is returned 958 * dest_desc - Where the copied object is returned
959 * walk_state - Current walk state
959 * 960 *
960 * RETURN: Status 961 * RETURN: Status
961 * 962 *
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 3f4602b8f287..cada73ffdfa7 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -831,7 +831,7 @@ static void acpi_battery_notify(struct acpi_device *device, u32 event)
831 dev_name(&device->dev), event, 831 dev_name(&device->dev), event,
832 acpi_battery_present(battery)); 832 acpi_battery_present(battery));
833#ifdef CONFIG_ACPI_SYSFS_POWER 833#ifdef CONFIG_ACPI_SYSFS_POWER
834 /* acpi_batter_update could remove power_supply object */ 834 /* acpi_battery_update could remove power_supply object */
835 if (battery->bat.dev) 835 if (battery->bat.dev)
836 kobject_uevent(&battery->bat.dev->kobj, KOBJ_CHANGE); 836 kobject_uevent(&battery->bat.dev->kobj, KOBJ_CHANGE);
837#endif 837#endif
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 741191524353..65f7e335f122 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -344,6 +344,152 @@ bool acpi_bus_can_wakeup(acpi_handle handle)
344 344
345EXPORT_SYMBOL(acpi_bus_can_wakeup); 345EXPORT_SYMBOL(acpi_bus_can_wakeup);
346 346
347static void acpi_print_osc_error(acpi_handle handle,
348 struct acpi_osc_context *context, char *error)
349{
350 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER};
351 int i;
352
353 if (ACPI_FAILURE(acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer)))
354 printk(KERN_DEBUG "%s\n", error);
355 else {
356 printk(KERN_DEBUG "%s:%s\n", (char *)buffer.pointer, error);
357 kfree(buffer.pointer);
358 }
359 printk(KERN_DEBUG"_OSC request data:");
360 for (i = 0; i < context->cap.length; i += sizeof(u32))
361 printk("%x ", *((u32 *)(context->cap.pointer + i)));
362 printk("\n");
363}
364
365static u8 hex_val(unsigned char c)
366{
367 return isdigit(c) ? c - '0' : toupper(c) - 'A' + 10;
368}
369
370static acpi_status acpi_str_to_uuid(char *str, u8 *uuid)
371{
372 int i;
373 static int opc_map_to_uuid[16] = {6, 4, 2, 0, 11, 9, 16, 14, 19, 21,
374 24, 26, 28, 30, 32, 34};
375
376 if (strlen(str) != 36)
377 return AE_BAD_PARAMETER;
378 for (i = 0; i < 36; i++) {
379 if (i == 8 || i == 13 || i == 18 || i == 23) {
380 if (str[i] != '-')
381 return AE_BAD_PARAMETER;
382 } else if (!isxdigit(str[i]))
383 return AE_BAD_PARAMETER;
384 }
385 for (i = 0; i < 16; i++) {
386 uuid[i] = hex_val(str[opc_map_to_uuid[i]]) << 4;
387 uuid[i] |= hex_val(str[opc_map_to_uuid[i] + 1]);
388 }
389 return AE_OK;
390}
391
392acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context)
393{
394 acpi_status status;
395 struct acpi_object_list input;
396 union acpi_object in_params[4];
397 union acpi_object *out_obj;
398 u8 uuid[16];
399 u32 errors;
400
401 if (!context)
402 return AE_ERROR;
403 if (ACPI_FAILURE(acpi_str_to_uuid(context->uuid_str, uuid)))
404 return AE_ERROR;
405 context->ret.length = ACPI_ALLOCATE_BUFFER;
406 context->ret.pointer = NULL;
407
408 /* Setting up input parameters */
409 input.count = 4;
410 input.pointer = in_params;
411 in_params[0].type = ACPI_TYPE_BUFFER;
412 in_params[0].buffer.length = 16;
413 in_params[0].buffer.pointer = uuid;
414 in_params[1].type = ACPI_TYPE_INTEGER;
415 in_params[1].integer.value = context->rev;
416 in_params[2].type = ACPI_TYPE_INTEGER;
417 in_params[2].integer.value = context->cap.length/sizeof(u32);
418 in_params[3].type = ACPI_TYPE_BUFFER;
419 in_params[3].buffer.length = context->cap.length;
420 in_params[3].buffer.pointer = context->cap.pointer;
421
422 status = acpi_evaluate_object(handle, "_OSC", &input, &context->ret);
423 if (ACPI_FAILURE(status))
424 return status;
425
426 /* return buffer should have the same length as cap buffer */
427 if (context->ret.length != context->cap.length)
428 return AE_NULL_OBJECT;
429
430 out_obj = context->ret.pointer;
431 if (out_obj->type != ACPI_TYPE_BUFFER) {
432 acpi_print_osc_error(handle, context,
433 "_OSC evaluation returned wrong type");
434 status = AE_TYPE;
435 goto out_kfree;
436 }
437 /* Need to ignore the bit0 in result code */
438 errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0);
439 if (errors) {
440 if (errors & OSC_REQUEST_ERROR)
441 acpi_print_osc_error(handle, context,
442 "_OSC request failed");
443 if (errors & OSC_INVALID_UUID_ERROR)
444 acpi_print_osc_error(handle, context,
445 "_OSC invalid UUID");
446 if (errors & OSC_INVALID_REVISION_ERROR)
447 acpi_print_osc_error(handle, context,
448 "_OSC invalid revision");
449 if (errors & OSC_CAPABILITIES_MASK_ERROR) {
450 if (((u32 *)context->cap.pointer)[OSC_QUERY_TYPE]
451 & OSC_QUERY_ENABLE)
452 goto out_success;
453 status = AE_SUPPORT;
454 goto out_kfree;
455 }
456 status = AE_ERROR;
457 goto out_kfree;
458 }
459out_success:
460 return AE_OK;
461
462out_kfree:
463 kfree(context->ret.pointer);
464 context->ret.pointer = NULL;
465 return status;
466}
467EXPORT_SYMBOL(acpi_run_osc);
468
469static u8 sb_uuid_str[] = "0811B06E-4A27-44F9-8D60-3CBBC22E7B48";
470static void acpi_bus_osc_support(void)
471{
472 u32 capbuf[2];
473 struct acpi_osc_context context = {
474 .uuid_str = sb_uuid_str,
475 .rev = 1,
476 .cap.length = 8,
477 .cap.pointer = capbuf,
478 };
479 acpi_handle handle;
480
481 capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
482 capbuf[OSC_SUPPORT_TYPE] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */
483#ifdef CONFIG_ACPI_PROCESSOR_AGGREGATOR
484 capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PAD_SUPPORT;
485#endif
486 if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle)))
487 return;
488 if (ACPI_SUCCESS(acpi_run_osc(handle, &context)))
489 kfree(context.ret.pointer);
490 /* do we need to check the returned cap? Sounds no */
491}
492
347/* -------------------------------------------------------------------------- 493/* --------------------------------------------------------------------------
348 Event Management 494 Event Management
349 -------------------------------------------------------------------------- */ 495 -------------------------------------------------------------------------- */
@@ -734,6 +880,8 @@ static int __init acpi_bus_init(void)
734 status = acpi_ec_ecdt_probe(); 880 status = acpi_ec_ecdt_probe();
735 /* Ignore result. Not having an ECDT is not fatal. */ 881 /* Ignore result. Not having an ECDT is not fatal. */
736 882
883 acpi_bus_osc_support();
884
737 status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION); 885 status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION);
738 if (ACPI_FAILURE(status)) { 886 if (ACPI_FAILURE(status)) {
739 printk(KERN_ERR PREFIX "Unable to initialize ACPI objects\n"); 887 printk(KERN_ERR PREFIX "Unable to initialize ACPI objects\n");
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 0c9c6a9a002c..8a95e8329df7 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -282,6 +282,13 @@ static int acpi_lid_send_state(struct acpi_device *device)
282 if (ret == NOTIFY_DONE) 282 if (ret == NOTIFY_DONE)
283 ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, 283 ret = blocking_notifier_call_chain(&acpi_lid_notifier, state,
284 device); 284 device);
285 if (ret == NOTIFY_DONE || ret == NOTIFY_OK) {
286 /*
287 * It is also regarded as success if the notifier_chain
288 * returns NOTIFY_OK or NOTIFY_DONE.
289 */
290 ret = 0;
291 }
285 return ret; 292 return ret;
286} 293}
287 294
diff --git a/drivers/acpi/debug.c b/drivers/acpi/debug.c
index 8a690c3b8e23..cc421b7ae166 100644
--- a/drivers/acpi/debug.c
+++ b/drivers/acpi/debug.c
@@ -8,6 +8,7 @@
8#include <linux/module.h> 8#include <linux/module.h>
9#include <linux/kernel.h> 9#include <linux/kernel.h>
10#include <linux/moduleparam.h> 10#include <linux/moduleparam.h>
11#include <linux/debugfs.h>
11#include <asm/uaccess.h> 12#include <asm/uaccess.h>
12#include <acpi/acpi_drivers.h> 13#include <acpi/acpi_drivers.h>
13 14
@@ -196,6 +197,80 @@ module_param_call(trace_state, param_set_trace_state, param_get_trace_state,
196 NULL, 0644); 197 NULL, 0644);
197 198
198/* -------------------------------------------------------------------------- 199/* --------------------------------------------------------------------------
200 DebugFS Interface
201 -------------------------------------------------------------------------- */
202
203static ssize_t cm_write(struct file *file, const char __user *user_buf,
204 size_t count, loff_t *ppos)
205{
206 static char *buf;
207 static int uncopied_bytes;
208 struct acpi_table_header table;
209 acpi_status status;
210
211 if (!(*ppos)) {
212 /* parse the table header to get the table length */
213 if (count <= sizeof(struct acpi_table_header))
214 return -EINVAL;
215 if (copy_from_user(&table, user_buf,
216 sizeof(struct acpi_table_header)))
217 return -EFAULT;
218 uncopied_bytes = table.length;
219 buf = kzalloc(uncopied_bytes, GFP_KERNEL);
220 if (!buf)
221 return -ENOMEM;
222 }
223
224 if (uncopied_bytes < count) {
225 kfree(buf);
226 return -EINVAL;
227 }
228
229 if (copy_from_user(buf + (*ppos), user_buf, count)) {
230 kfree(buf);
231 return -EFAULT;
232 }
233
234 uncopied_bytes -= count;
235 *ppos += count;
236
237 if (!uncopied_bytes) {
238 status = acpi_install_method(buf);
239 kfree(buf);
240 if (ACPI_FAILURE(status))
241 return -EINVAL;
242 add_taint(TAINT_OVERRIDDEN_ACPI_TABLE);
243 }
244
245 return count;
246}
247
248static const struct file_operations cm_fops = {
249 .write = cm_write,
250};
251
252static int acpi_debugfs_init(void)
253{
254 struct dentry *acpi_dir, *cm_dentry;
255
256 acpi_dir = debugfs_create_dir("acpi", NULL);
257 if (!acpi_dir)
258 goto err;
259
260 cm_dentry = debugfs_create_file("custom_method", S_IWUGO,
261 acpi_dir, NULL, &cm_fops);
262 if (!cm_dentry)
263 goto err;
264
265 return 0;
266
267err:
268 if (acpi_dir)
269 debugfs_remove(acpi_dir);
270 return -EINVAL;
271}
272
273/* --------------------------------------------------------------------------
199 FS Interface (/proc) 274 FS Interface (/proc)
200 -------------------------------------------------------------------------- */ 275 -------------------------------------------------------------------------- */
201#ifdef CONFIG_ACPI_PROCFS 276#ifdef CONFIG_ACPI_PROCFS
@@ -286,7 +361,7 @@ static const struct file_operations acpi_system_debug_proc_fops = {
286}; 361};
287#endif 362#endif
288 363
289int __init acpi_debug_init(void) 364int __init acpi_procfs_init(void)
290{ 365{
291#ifdef CONFIG_ACPI_PROCFS 366#ifdef CONFIG_ACPI_PROCFS
292 struct proc_dir_entry *entry; 367 struct proc_dir_entry *entry;
@@ -321,3 +396,10 @@ int __init acpi_debug_init(void)
321 return 0; 396 return 0;
322#endif 397#endif
323} 398}
399
400int __init acpi_debug_init(void)
401{
402 acpi_debugfs_init();
403 acpi_procfs_init();
404 return 0;
405}
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 30be3c148f7e..bbc2c1315c47 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -50,7 +50,6 @@ MODULE_PARM_DESC(immediate_undock, "1 (default) will cause the driver to "
50 " before undocking"); 50 " before undocking");
51 51
52static struct atomic_notifier_head dock_notifier_list; 52static struct atomic_notifier_head dock_notifier_list;
53static char dock_device_name[] = "dock";
54 53
55static const struct acpi_device_id dock_device_ids[] = { 54static const struct acpi_device_id dock_device_ids[] = {
56 {"LNXDOCK", 0}, 55 {"LNXDOCK", 0},
@@ -93,40 +92,30 @@ struct dock_dependent_device {
93 * Dock Dependent device functions * 92 * Dock Dependent device functions *
94 *****************************************************************************/ 93 *****************************************************************************/
95/** 94/**
96 * alloc_dock_dependent_device - allocate and init a dependent device 95 * add_dock_dependent_device - associate a device with the dock station
97 * @handle: the acpi_handle of the dependent device 96 * @ds: The dock station
97 * @handle: handle of the dependent device
98 * 98 *
99 * Allocate memory for a dependent device structure for a device referenced 99 * Add the dependent device to the dock's dependent device list.
100 * by the acpi handle
101 */ 100 */
102static struct dock_dependent_device * 101static int
103alloc_dock_dependent_device(acpi_handle handle) 102add_dock_dependent_device(struct dock_station *ds, acpi_handle handle)
104{ 103{
105 struct dock_dependent_device *dd; 104 struct dock_dependent_device *dd;
106 105
107 dd = kzalloc(sizeof(*dd), GFP_KERNEL); 106 dd = kzalloc(sizeof(*dd), GFP_KERNEL);
108 if (dd) { 107 if (!dd)
109 dd->handle = handle; 108 return -ENOMEM;
110 INIT_LIST_HEAD(&dd->list); 109
111 INIT_LIST_HEAD(&dd->hotplug_list); 110 dd->handle = handle;
112 } 111 INIT_LIST_HEAD(&dd->list);
113 return dd; 112 INIT_LIST_HEAD(&dd->hotplug_list);
114}
115 113
116/**
117 * add_dock_dependent_device - associate a device with the dock station
118 * @ds: The dock station
119 * @dd: The dependent device
120 *
121 * Add the dependent device to the dock's dependent device list.
122 */
123static void
124add_dock_dependent_device(struct dock_station *ds,
125 struct dock_dependent_device *dd)
126{
127 spin_lock(&ds->dd_lock); 114 spin_lock(&ds->dd_lock);
128 list_add_tail(&dd->list, &ds->dependent_devices); 115 list_add_tail(&dd->list, &ds->dependent_devices);
129 spin_unlock(&ds->dd_lock); 116 spin_unlock(&ds->dd_lock);
117
118 return 0;
130} 119}
131 120
132/** 121/**
@@ -249,6 +238,7 @@ static int is_battery(acpi_handle handle)
249static int is_ejectable_bay(acpi_handle handle) 238static int is_ejectable_bay(acpi_handle handle)
250{ 239{
251 acpi_handle phandle; 240 acpi_handle phandle;
241
252 if (!is_ejectable(handle)) 242 if (!is_ejectable(handle))
253 return 0; 243 return 0;
254 if (is_battery(handle) || is_ata(handle)) 244 if (is_battery(handle) || is_ata(handle))
@@ -275,14 +265,13 @@ int is_dock_device(acpi_handle handle)
275 265
276 if (is_dock(handle)) 266 if (is_dock(handle))
277 return 1; 267 return 1;
278 list_for_each_entry(dock_station, &dock_stations, sibling) { 268
269 list_for_each_entry(dock_station, &dock_stations, sibling)
279 if (find_dock_dependent_device(dock_station, handle)) 270 if (find_dock_dependent_device(dock_station, handle))
280 return 1; 271 return 1;
281 }
282 272
283 return 0; 273 return 0;
284} 274}
285
286EXPORT_SYMBOL_GPL(is_dock_device); 275EXPORT_SYMBOL_GPL(is_dock_device);
287 276
288/** 277/**
@@ -305,8 +294,6 @@ static int dock_present(struct dock_station *ds)
305 return 0; 294 return 0;
306} 295}
307 296
308
309
310/** 297/**
311 * dock_create_acpi_device - add new devices to acpi 298 * dock_create_acpi_device - add new devices to acpi
312 * @handle - handle of the device to add 299 * @handle - handle of the device to add
@@ -320,7 +307,7 @@ static int dock_present(struct dock_station *ds)
320 */ 307 */
321static struct acpi_device * dock_create_acpi_device(acpi_handle handle) 308static struct acpi_device * dock_create_acpi_device(acpi_handle handle)
322{ 309{
323 struct acpi_device *device = NULL; 310 struct acpi_device *device;
324 struct acpi_device *parent_device; 311 struct acpi_device *parent_device;
325 acpi_handle parent; 312 acpi_handle parent;
326 int ret; 313 int ret;
@@ -337,8 +324,7 @@ static struct acpi_device * dock_create_acpi_device(acpi_handle handle)
337 ret = acpi_bus_add(&device, parent_device, handle, 324 ret = acpi_bus_add(&device, parent_device, handle,
338 ACPI_BUS_TYPE_DEVICE); 325 ACPI_BUS_TYPE_DEVICE);
339 if (ret) { 326 if (ret) {
340 pr_debug("error adding bus, %x\n", 327 pr_debug("error adding bus, %x\n", -ret);
341 -ret);
342 return NULL; 328 return NULL;
343 } 329 }
344 } 330 }
@@ -364,7 +350,6 @@ static void dock_remove_acpi_device(acpi_handle handle)
364 } 350 }
365} 351}
366 352
367
368/** 353/**
369 * hotplug_dock_devices - insert or remove devices on the dock station 354 * hotplug_dock_devices - insert or remove devices on the dock station
370 * @ds: the dock station 355 * @ds: the dock station
@@ -384,10 +369,9 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event)
384 /* 369 /*
385 * First call driver specific hotplug functions 370 * First call driver specific hotplug functions
386 */ 371 */
387 list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list) { 372 list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list)
388 if (dd->ops && dd->ops->handler) 373 if (dd->ops && dd->ops->handler)
389 dd->ops->handler(dd->handle, event, dd->context); 374 dd->ops->handler(dd->handle, event, dd->context);
390 }
391 375
392 /* 376 /*
393 * Now make sure that an acpi_device is created for each 377 * Now make sure that an acpi_device is created for each
@@ -426,6 +410,7 @@ static void dock_event(struct dock_station *ds, u32 event, int num)
426 list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list) 410 list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list)
427 if (dd->ops && dd->ops->uevent) 411 if (dd->ops && dd->ops->uevent)
428 dd->ops->uevent(dd->handle, event, dd->context); 412 dd->ops->uevent(dd->handle, event, dd->context);
413
429 if (num != DOCK_EVENT) 414 if (num != DOCK_EVENT)
430 kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); 415 kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
431} 416}
@@ -456,8 +441,8 @@ static void eject_dock(struct dock_station *ds)
456 arg.type = ACPI_TYPE_INTEGER; 441 arg.type = ACPI_TYPE_INTEGER;
457 arg.integer.value = 1; 442 arg.integer.value = 1;
458 443
459 if (ACPI_FAILURE(acpi_evaluate_object(ds->handle, "_EJ0", 444 status = acpi_evaluate_object(ds->handle, "_EJ0", &arg_list, NULL);
460 &arg_list, NULL))) 445 if (ACPI_FAILURE(status))
461 pr_debug("Failed to evaluate _EJ0!\n"); 446 pr_debug("Failed to evaluate _EJ0!\n");
462} 447}
463 448
@@ -577,7 +562,6 @@ int register_dock_notifier(struct notifier_block *nb)
577 562
578 return atomic_notifier_chain_register(&dock_notifier_list, nb); 563 return atomic_notifier_chain_register(&dock_notifier_list, nb);
579} 564}
580
581EXPORT_SYMBOL_GPL(register_dock_notifier); 565EXPORT_SYMBOL_GPL(register_dock_notifier);
582 566
583/** 567/**
@@ -591,7 +575,6 @@ void unregister_dock_notifier(struct notifier_block *nb)
591 575
592 atomic_notifier_chain_unregister(&dock_notifier_list, nb); 576 atomic_notifier_chain_unregister(&dock_notifier_list, nb);
593} 577}
594
595EXPORT_SYMBOL_GPL(unregister_dock_notifier); 578EXPORT_SYMBOL_GPL(unregister_dock_notifier);
596 579
597/** 580/**
@@ -636,7 +619,6 @@ register_hotplug_dock_device(acpi_handle handle, struct acpi_dock_ops *ops,
636 619
637 return ret; 620 return ret;
638} 621}
639
640EXPORT_SYMBOL_GPL(register_hotplug_dock_device); 622EXPORT_SYMBOL_GPL(register_hotplug_dock_device);
641 623
642/** 624/**
@@ -657,7 +639,6 @@ void unregister_hotplug_dock_device(acpi_handle handle)
657 dock_del_hotplug_device(dock_station, dd); 639 dock_del_hotplug_device(dock_station, dd);
658 } 640 }
659} 641}
660
661EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device); 642EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device);
662 643
663/** 644/**
@@ -772,7 +753,7 @@ struct dock_data {
772 753
773static void acpi_dock_deferred_cb(void *context) 754static void acpi_dock_deferred_cb(void *context)
774{ 755{
775 struct dock_data *data = (struct dock_data *)context; 756 struct dock_data *data = context;
776 757
777 dock_notify(data->handle, data->event, data->ds); 758 dock_notify(data->handle, data->event, data->ds);
778 kfree(data); 759 kfree(data);
@@ -782,23 +763,22 @@ static int acpi_dock_notifier_call(struct notifier_block *this,
782 unsigned long event, void *data) 763 unsigned long event, void *data)
783{ 764{
784 struct dock_station *dock_station; 765 struct dock_station *dock_station;
785 acpi_handle handle = (acpi_handle)data; 766 acpi_handle handle = data;
786 767
787 if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK 768 if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK
788 && event != ACPI_NOTIFY_EJECT_REQUEST) 769 && event != ACPI_NOTIFY_EJECT_REQUEST)
789 return 0; 770 return 0;
790 list_for_each_entry(dock_station, &dock_stations, sibling) { 771 list_for_each_entry(dock_station, &dock_stations, sibling) {
791 if (dock_station->handle == handle) { 772 if (dock_station->handle == handle) {
792 struct dock_data *dock_data; 773 struct dock_data *dd;
793 774
794 dock_data = kmalloc(sizeof(*dock_data), GFP_KERNEL); 775 dd = kmalloc(sizeof(*dd), GFP_KERNEL);
795 if (!dock_data) 776 if (!dd)
796 return 0; 777 return 0;
797 dock_data->handle = handle; 778 dd->handle = handle;
798 dock_data->event = event; 779 dd->event = event;
799 dock_data->ds = dock_station; 780 dd->ds = dock_station;
800 acpi_os_hotplug_execute(acpi_dock_deferred_cb, 781 acpi_os_hotplug_execute(acpi_dock_deferred_cb, dd);
801 dock_data);
802 return 0 ; 782 return 0 ;
803 } 783 }
804 } 784 }
@@ -826,7 +806,6 @@ find_dock_devices(acpi_handle handle, u32 lvl, void *context, void **rv)
826 acpi_status status; 806 acpi_status status;
827 acpi_handle tmp, parent; 807 acpi_handle tmp, parent;
828 struct dock_station *ds = context; 808 struct dock_station *ds = context;
829 struct dock_dependent_device *dd;
830 809
831 status = acpi_bus_get_ejd(handle, &tmp); 810 status = acpi_bus_get_ejd(handle, &tmp);
832 if (ACPI_FAILURE(status)) { 811 if (ACPI_FAILURE(status)) {
@@ -840,11 +819,9 @@ find_dock_devices(acpi_handle handle, u32 lvl, void *context, void **rv)
840 goto fdd_out; 819 goto fdd_out;
841 } 820 }
842 821
843 if (tmp == ds->handle) { 822 if (tmp == ds->handle)
844 dd = alloc_dock_dependent_device(handle); 823 add_dock_dependent_device(ds, handle);
845 if (dd) 824
846 add_dock_dependent_device(ds, dd);
847 }
848fdd_out: 825fdd_out:
849 return AE_OK; 826 return AE_OK;
850} 827}
@@ -857,8 +834,7 @@ static ssize_t show_docked(struct device *dev,
857{ 834{
858 struct acpi_device *tmp; 835 struct acpi_device *tmp;
859 836
860 struct dock_station *dock_station = *((struct dock_station **) 837 struct dock_station *dock_station = dev->platform_data;
861 dev->platform_data);
862 838
863 if (ACPI_SUCCESS(acpi_bus_get_device(dock_station->handle, &tmp))) 839 if (ACPI_SUCCESS(acpi_bus_get_device(dock_station->handle, &tmp)))
864 return snprintf(buf, PAGE_SIZE, "1\n"); 840 return snprintf(buf, PAGE_SIZE, "1\n");
@@ -872,8 +848,7 @@ static DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
872static ssize_t show_flags(struct device *dev, 848static ssize_t show_flags(struct device *dev,
873 struct device_attribute *attr, char *buf) 849 struct device_attribute *attr, char *buf)
874{ 850{
875 struct dock_station *dock_station = *((struct dock_station **) 851 struct dock_station *dock_station = dev->platform_data;
876 dev->platform_data);
877 return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags); 852 return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags);
878 853
879} 854}
@@ -886,8 +861,7 @@ static ssize_t write_undock(struct device *dev, struct device_attribute *attr,
886 const char *buf, size_t count) 861 const char *buf, size_t count)
887{ 862{
888 int ret; 863 int ret;
889 struct dock_station *dock_station = *((struct dock_station **) 864 struct dock_station *dock_station = dev->platform_data;
890 dev->platform_data);
891 865
892 if (!count) 866 if (!count)
893 return -EINVAL; 867 return -EINVAL;
@@ -905,8 +879,7 @@ static ssize_t show_dock_uid(struct device *dev,
905 struct device_attribute *attr, char *buf) 879 struct device_attribute *attr, char *buf)
906{ 880{
907 unsigned long long lbuf; 881 unsigned long long lbuf;
908 struct dock_station *dock_station = *((struct dock_station **) 882 struct dock_station *dock_station = dev->platform_data;
909 dev->platform_data);
910 acpi_status status = acpi_evaluate_integer(dock_station->handle, 883 acpi_status status = acpi_evaluate_integer(dock_station->handle,
911 "_UID", NULL, &lbuf); 884 "_UID", NULL, &lbuf);
912 if (ACPI_FAILURE(status)) 885 if (ACPI_FAILURE(status))
@@ -919,8 +892,7 @@ static DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL);
919static ssize_t show_dock_type(struct device *dev, 892static ssize_t show_dock_type(struct device *dev,
920 struct device_attribute *attr, char *buf) 893 struct device_attribute *attr, char *buf)
921{ 894{
922 struct dock_station *dock_station = *((struct dock_station **) 895 struct dock_station *dock_station = dev->platform_data;
923 dev->platform_data);
924 char *type; 896 char *type;
925 897
926 if (dock_station->flags & DOCK_IS_DOCK) 898 if (dock_station->flags & DOCK_IS_DOCK)
@@ -936,6 +908,19 @@ static ssize_t show_dock_type(struct device *dev,
936} 908}
937static DEVICE_ATTR(type, S_IRUGO, show_dock_type, NULL); 909static DEVICE_ATTR(type, S_IRUGO, show_dock_type, NULL);
938 910
911static struct attribute *dock_attributes[] = {
912 &dev_attr_docked.attr,
913 &dev_attr_flags.attr,
914 &dev_attr_undock.attr,
915 &dev_attr_uid.attr,
916 &dev_attr_type.attr,
917 NULL
918};
919
920static struct attribute_group dock_attribute_group = {
921 .attrs = dock_attributes
922};
923
939/** 924/**
940 * dock_add - add a new dock station 925 * dock_add - add a new dock station
941 * @handle: the dock station handle 926 * @handle: the dock station handle
@@ -945,39 +930,30 @@ static DEVICE_ATTR(type, S_IRUGO, show_dock_type, NULL);
945 */ 930 */
946static int dock_add(acpi_handle handle) 931static int dock_add(acpi_handle handle)
947{ 932{
948 int ret; 933 int ret, id;
949 struct dock_dependent_device *dd; 934 struct dock_station ds, *dock_station;
950 struct dock_station *dock_station; 935 struct platform_device *dd;
951 struct platform_device *dock_device; 936
937 id = dock_station_count;
938 dd = platform_device_register_data(NULL, "dock", id, &ds, sizeof(ds));
939 if (IS_ERR(dd))
940 return PTR_ERR(dd);
941
942 dock_station = dd->dev.platform_data;
952 943
953 /* allocate & initialize the dock_station private data */
954 dock_station = kzalloc(sizeof(*dock_station), GFP_KERNEL);
955 if (!dock_station)
956 return -ENOMEM;
957 dock_station->handle = handle; 944 dock_station->handle = handle;
945 dock_station->dock_device = dd;
958 dock_station->last_dock_time = jiffies - HZ; 946 dock_station->last_dock_time = jiffies - HZ;
959 INIT_LIST_HEAD(&dock_station->dependent_devices); 947
960 INIT_LIST_HEAD(&dock_station->hotplug_devices);
961 INIT_LIST_HEAD(&dock_station->sibling);
962 spin_lock_init(&dock_station->dd_lock);
963 mutex_init(&dock_station->hp_lock); 948 mutex_init(&dock_station->hp_lock);
949 spin_lock_init(&dock_station->dd_lock);
950 INIT_LIST_HEAD(&dock_station->sibling);
951 INIT_LIST_HEAD(&dock_station->hotplug_devices);
964 ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list); 952 ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list);
965 953 INIT_LIST_HEAD(&dock_station->dependent_devices);
966 /* initialize platform device stuff */
967 dock_station->dock_device =
968 platform_device_register_simple(dock_device_name,
969 dock_station_count, NULL, 0);
970 dock_device = dock_station->dock_device;
971 if (IS_ERR(dock_device)) {
972 kfree(dock_station);
973 dock_station = NULL;
974 return PTR_ERR(dock_device);
975 }
976 platform_device_add_data(dock_device, &dock_station,
977 sizeof(struct dock_station *));
978 954
979 /* we want the dock device to send uevents */ 955 /* we want the dock device to send uevents */
980 dev_set_uevent_suppress(&dock_device->dev, 0); 956 dev_set_uevent_suppress(&dd->dev, 0);
981 957
982 if (is_dock(handle)) 958 if (is_dock(handle))
983 dock_station->flags |= DOCK_IS_DOCK; 959 dock_station->flags |= DOCK_IS_DOCK;
@@ -986,47 +962,9 @@ static int dock_add(acpi_handle handle)
986 if (is_battery(handle)) 962 if (is_battery(handle))
987 dock_station->flags |= DOCK_IS_BAT; 963 dock_station->flags |= DOCK_IS_BAT;
988 964
989 ret = device_create_file(&dock_device->dev, &dev_attr_docked); 965 ret = sysfs_create_group(&dd->dev.kobj, &dock_attribute_group);
990 if (ret) {
991 printk(KERN_ERR "Error %d adding sysfs file\n", ret);
992 platform_device_unregister(dock_device);
993 kfree(dock_station);
994 dock_station = NULL;
995 return ret;
996 }
997 ret = device_create_file(&dock_device->dev, &dev_attr_undock);
998 if (ret) {
999 printk(KERN_ERR "Error %d adding sysfs file\n", ret);
1000 device_remove_file(&dock_device->dev, &dev_attr_docked);
1001 platform_device_unregister(dock_device);
1002 kfree(dock_station);
1003 dock_station = NULL;
1004 return ret;
1005 }
1006 ret = device_create_file(&dock_device->dev, &dev_attr_uid);
1007 if (ret) {
1008 printk(KERN_ERR "Error %d adding sysfs file\n", ret);
1009 device_remove_file(&dock_device->dev, &dev_attr_docked);
1010 device_remove_file(&dock_device->dev, &dev_attr_undock);
1011 platform_device_unregister(dock_device);
1012 kfree(dock_station);
1013 dock_station = NULL;
1014 return ret;
1015 }
1016 ret = device_create_file(&dock_device->dev, &dev_attr_flags);
1017 if (ret) {
1018 printk(KERN_ERR "Error %d adding sysfs file\n", ret);
1019 device_remove_file(&dock_device->dev, &dev_attr_docked);
1020 device_remove_file(&dock_device->dev, &dev_attr_undock);
1021 device_remove_file(&dock_device->dev, &dev_attr_uid);
1022 platform_device_unregister(dock_device);
1023 kfree(dock_station);
1024 dock_station = NULL;
1025 return ret;
1026 }
1027 ret = device_create_file(&dock_device->dev, &dev_attr_type);
1028 if (ret) 966 if (ret)
1029 printk(KERN_ERR"Error %d adding sysfs file\n", ret); 967 goto err_unregister;
1030 968
1031 /* Find dependent devices */ 969 /* Find dependent devices */
1032 acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 970 acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
@@ -1034,58 +972,43 @@ static int dock_add(acpi_handle handle)
1034 dock_station, NULL); 972 dock_station, NULL);
1035 973
1036 /* add the dock station as a device dependent on itself */ 974 /* add the dock station as a device dependent on itself */
1037 dd = alloc_dock_dependent_device(handle); 975 ret = add_dock_dependent_device(dock_station, handle);
1038 if (!dd) { 976 if (ret)
1039 kfree(dock_station); 977 goto err_rmgroup;
1040 dock_station = NULL;
1041 ret = -ENOMEM;
1042 goto dock_add_err_unregister;
1043 }
1044 add_dock_dependent_device(dock_station, dd);
1045 978
1046 dock_station_count++; 979 dock_station_count++;
1047 list_add(&dock_station->sibling, &dock_stations); 980 list_add(&dock_station->sibling, &dock_stations);
1048 return 0; 981 return 0;
1049 982
1050dock_add_err_unregister: 983err_rmgroup:
1051 device_remove_file(&dock_device->dev, &dev_attr_type); 984 sysfs_remove_group(&dd->dev.kobj, &dock_attribute_group);
1052 device_remove_file(&dock_device->dev, &dev_attr_docked); 985err_unregister:
1053 device_remove_file(&dock_device->dev, &dev_attr_undock); 986 platform_device_unregister(dd);
1054 device_remove_file(&dock_device->dev, &dev_attr_uid); 987 printk(KERN_ERR "%s encountered error %d\n", __func__, ret);
1055 device_remove_file(&dock_device->dev, &dev_attr_flags);
1056 platform_device_unregister(dock_device);
1057 kfree(dock_station);
1058 dock_station = NULL;
1059 return ret; 988 return ret;
1060} 989}
1061 990
1062/** 991/**
1063 * dock_remove - free up resources related to the dock station 992 * dock_remove - free up resources related to the dock station
1064 */ 993 */
1065static int dock_remove(struct dock_station *dock_station) 994static int dock_remove(struct dock_station *ds)
1066{ 995{
1067 struct dock_dependent_device *dd, *tmp; 996 struct dock_dependent_device *dd, *tmp;
1068 struct platform_device *dock_device = dock_station->dock_device; 997 struct platform_device *dock_device = ds->dock_device;
1069 998
1070 if (!dock_station_count) 999 if (!dock_station_count)
1071 return 0; 1000 return 0;
1072 1001
1073 /* remove dependent devices */ 1002 /* remove dependent devices */
1074 list_for_each_entry_safe(dd, tmp, &dock_station->dependent_devices, 1003 list_for_each_entry_safe(dd, tmp, &ds->dependent_devices, list)
1075 list) 1004 kfree(dd);
1076 kfree(dd); 1005
1006 list_del(&ds->sibling);
1077 1007
1078 /* cleanup sysfs */ 1008 /* cleanup sysfs */
1079 device_remove_file(&dock_device->dev, &dev_attr_type); 1009 sysfs_remove_group(&dock_device->dev.kobj, &dock_attribute_group);
1080 device_remove_file(&dock_device->dev, &dev_attr_docked);
1081 device_remove_file(&dock_device->dev, &dev_attr_undock);
1082 device_remove_file(&dock_device->dev, &dev_attr_uid);
1083 device_remove_file(&dock_device->dev, &dev_attr_flags);
1084 platform_device_unregister(dock_device); 1010 platform_device_unregister(dock_device);
1085 1011
1086 /* free dock station memory */
1087 kfree(dock_station);
1088 dock_station = NULL;
1089 return 0; 1012 return 0;
1090} 1013}
1091 1014
@@ -1103,11 +1026,10 @@ find_dock(acpi_handle handle, u32 lvl, void *context, void **rv)
1103{ 1026{
1104 acpi_status status = AE_OK; 1027 acpi_status status = AE_OK;
1105 1028
1106 if (is_dock(handle)) { 1029 if (is_dock(handle))
1107 if (dock_add(handle) >= 0) { 1030 if (dock_add(handle) >= 0)
1108 status = AE_CTRL_TERMINATE; 1031 status = AE_CTRL_TERMINATE;
1109 } 1032
1110 }
1111 return status; 1033 return status;
1112} 1034}
1113 1035
@@ -1145,8 +1067,7 @@ static int __init dock_init(void)
1145 1067
1146static void __exit dock_exit(void) 1068static void __exit dock_exit(void)
1147{ 1069{
1148 struct dock_station *dock_station; 1070 struct dock_station *tmp, *dock_station;
1149 struct dock_station *tmp;
1150 1071
1151 unregister_acpi_bus_notifier(&dock_acpi_notifier); 1072 unregister_acpi_bus_notifier(&dock_acpi_notifier);
1152 list_for_each_entry_safe(dock_station, tmp, &dock_stations, sibling) 1073 list_for_each_entry_safe(dock_station, tmp, &dock_stations, sibling)
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index f419849a0d3f..acf2ab249842 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -267,7 +267,7 @@ static int acpi_fan_add(struct acpi_device *device)
267 goto end; 267 goto end;
268 } 268 }
269 269
270 dev_info(&device->dev, "registered as cooling_device%d\n", cdev->id); 270 dev_dbg(&device->dev, "registered as cooling_device%d\n", cdev->id);
271 271
272 device->driver_data = cdev; 272 device->driver_data = cdev;
273 result = sysfs_create_link(&device->dev.kobj, 273 result = sysfs_create_link(&device->dev.kobj,
diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index 2be2fb66204e..7ad48dfc12db 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -28,6 +28,7 @@
28#include <linux/types.h> 28#include <linux/types.h>
29#include <linux/errno.h> 29#include <linux/errno.h>
30#include <linux/acpi.h> 30#include <linux/acpi.h>
31#include <linux/numa.h>
31#include <acpi/acpi_bus.h> 32#include <acpi/acpi_bus.h>
32 33
33#define PREFIX "ACPI: " 34#define PREFIX "ACPI: "
@@ -40,14 +41,14 @@ static nodemask_t nodes_found_map = NODE_MASK_NONE;
40 41
41/* maps to convert between proximity domain and logical node ID */ 42/* maps to convert between proximity domain and logical node ID */
42static int pxm_to_node_map[MAX_PXM_DOMAINS] 43static int pxm_to_node_map[MAX_PXM_DOMAINS]
43 = { [0 ... MAX_PXM_DOMAINS - 1] = NID_INVAL }; 44 = { [0 ... MAX_PXM_DOMAINS - 1] = NUMA_NO_NODE };
44static int node_to_pxm_map[MAX_NUMNODES] 45static int node_to_pxm_map[MAX_NUMNODES]
45 = { [0 ... MAX_NUMNODES - 1] = PXM_INVAL }; 46 = { [0 ... MAX_NUMNODES - 1] = PXM_INVAL };
46 47
47int pxm_to_node(int pxm) 48int pxm_to_node(int pxm)
48{ 49{
49 if (pxm < 0) 50 if (pxm < 0)
50 return NID_INVAL; 51 return NUMA_NO_NODE;
51 return pxm_to_node_map[pxm]; 52 return pxm_to_node_map[pxm];
52} 53}
53 54
@@ -68,9 +69,9 @@ int acpi_map_pxm_to_node(int pxm)
68{ 69{
69 int node = pxm_to_node_map[pxm]; 70 int node = pxm_to_node_map[pxm];
70 71
71 if (node < 0){ 72 if (node < 0) {
72 if (nodes_weight(nodes_found_map) >= MAX_NUMNODES) 73 if (nodes_weight(nodes_found_map) >= MAX_NUMNODES)
73 return NID_INVAL; 74 return NUMA_NO_NODE;
74 node = first_unset_node(nodes_found_map); 75 node = first_unset_node(nodes_found_map);
75 __acpi_map_pxm_to_node(pxm, node); 76 __acpi_map_pxm_to_node(pxm, node);
76 node_set(node, nodes_found_map); 77 node_set(node, nodes_found_map);
@@ -79,16 +80,6 @@ int acpi_map_pxm_to_node(int pxm)
79 return node; 80 return node;
80} 81}
81 82
82#if 0
83void __cpuinit acpi_unmap_pxm_to_node(int node)
84{
85 int pxm = node_to_pxm_map[node];
86 pxm_to_node_map[pxm] = NID_INVAL;
87 node_to_pxm_map[node] = PXM_INVAL;
88 node_clear(node, nodes_found_map);
89}
90#endif /* 0 */
91
92static void __init 83static void __init
93acpi_table_print_srat_entry(struct acpi_subtable_header *header) 84acpi_table_print_srat_entry(struct acpi_subtable_header *header)
94{ 85{
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 7c1c59ea9ec6..02e8464e480f 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -1118,7 +1118,7 @@ __setup("acpi_enforce_resources=", acpi_enforce_resources_setup);
1118 1118
1119/* Check for resource conflicts between ACPI OperationRegions and native 1119/* Check for resource conflicts between ACPI OperationRegions and native
1120 * drivers */ 1120 * drivers */
1121int acpi_check_resource_conflict(struct resource *res) 1121int acpi_check_resource_conflict(const struct resource *res)
1122{ 1122{
1123 struct acpi_res_list *res_list_elem; 1123 struct acpi_res_list *res_list_elem;
1124 int ioport; 1124 int ioport;
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 1af808171d46..101cce3681d1 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -202,72 +202,24 @@ static void acpi_pci_bridge_scan(struct acpi_device *device)
202 } 202 }
203} 203}
204 204
205static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40, 205static u8 pci_osc_uuid_str[] = "33DB4D5B-1FF7-401C-9657-7441C03DD766";
206 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66};
207 206
208static acpi_status acpi_pci_run_osc(acpi_handle handle, 207static acpi_status acpi_pci_run_osc(acpi_handle handle,
209 const u32 *capbuf, u32 *retval) 208 const u32 *capbuf, u32 *retval)
210{ 209{
210 struct acpi_osc_context context = {
211 .uuid_str = pci_osc_uuid_str,
212 .rev = 1,
213 .cap.length = 12,
214 .cap.pointer = (void *)capbuf,
215 };
211 acpi_status status; 216 acpi_status status;
212 struct acpi_object_list input;
213 union acpi_object in_params[4];
214 struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
215 union acpi_object *out_obj;
216 u32 errors;
217
218 /* Setting up input parameters */
219 input.count = 4;
220 input.pointer = in_params;
221 in_params[0].type = ACPI_TYPE_BUFFER;
222 in_params[0].buffer.length = 16;
223 in_params[0].buffer.pointer = OSC_UUID;
224 in_params[1].type = ACPI_TYPE_INTEGER;
225 in_params[1].integer.value = 1;
226 in_params[2].type = ACPI_TYPE_INTEGER;
227 in_params[2].integer.value = 3;
228 in_params[3].type = ACPI_TYPE_BUFFER;
229 in_params[3].buffer.length = 12;
230 in_params[3].buffer.pointer = (u8 *)capbuf;
231
232 status = acpi_evaluate_object(handle, "_OSC", &input, &output);
233 if (ACPI_FAILURE(status))
234 return status;
235 217
236 if (!output.length) 218 status = acpi_run_osc(handle, &context);
237 return AE_NULL_OBJECT; 219 if (ACPI_SUCCESS(status)) {
238 220 *retval = *((u32 *)(context.ret.pointer + 8));
239 out_obj = output.pointer; 221 kfree(context.ret.pointer);
240 if (out_obj->type != ACPI_TYPE_BUFFER) {
241 printk(KERN_DEBUG "_OSC evaluation returned wrong type\n");
242 status = AE_TYPE;
243 goto out_kfree;
244 }
245 /* Need to ignore the bit0 in result code */
246 errors = *((u32 *)out_obj->buffer.pointer) & ~(1 << 0);
247 if (errors) {
248 if (errors & OSC_REQUEST_ERROR)
249 printk(KERN_DEBUG "_OSC request failed\n");
250 if (errors & OSC_INVALID_UUID_ERROR)
251 printk(KERN_DEBUG "_OSC invalid UUID\n");
252 if (errors & OSC_INVALID_REVISION_ERROR)
253 printk(KERN_DEBUG "_OSC invalid revision\n");
254 if (errors & OSC_CAPABILITIES_MASK_ERROR) {
255 if (capbuf[OSC_QUERY_TYPE] & OSC_QUERY_ENABLE)
256 goto out_success;
257 printk(KERN_DEBUG
258 "Firmware did not grant requested _OSC control\n");
259 status = AE_SUPPORT;
260 goto out_kfree;
261 }
262 status = AE_ERROR;
263 goto out_kfree;
264 } 222 }
265out_success:
266 *retval = *((u32 *)(out_obj->buffer.pointer + 8));
267 status = AE_OK;
268
269out_kfree:
270 kfree(output.pointer);
271 return status; 223 return status;
272} 224}
273 225
@@ -277,10 +229,10 @@ static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, u32 flags)
277 u32 support_set, result, capbuf[3]; 229 u32 support_set, result, capbuf[3];
278 230
279 /* do _OSC query for all possible controls */ 231 /* do _OSC query for all possible controls */
280 support_set = root->osc_support_set | (flags & OSC_SUPPORT_MASKS); 232 support_set = root->osc_support_set | (flags & OSC_PCI_SUPPORT_MASKS);
281 capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; 233 capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
282 capbuf[OSC_SUPPORT_TYPE] = support_set; 234 capbuf[OSC_SUPPORT_TYPE] = support_set;
283 capbuf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS; 235 capbuf[OSC_CONTROL_TYPE] = OSC_PCI_CONTROL_MASKS;
284 236
285 status = acpi_pci_run_osc(root->device->handle, capbuf, &result); 237 status = acpi_pci_run_osc(root->device->handle, capbuf, &result);
286 if (ACPI_SUCCESS(status)) { 238 if (ACPI_SUCCESS(status)) {
@@ -427,7 +379,7 @@ acpi_status acpi_pci_osc_control_set(acpi_handle handle, u32 flags)
427 if (ACPI_FAILURE(status)) 379 if (ACPI_FAILURE(status))
428 return status; 380 return status;
429 381
430 control_req = (flags & OSC_CONTROL_MASKS); 382 control_req = (flags & OSC_PCI_CONTROL_MASKS);
431 if (!control_req) 383 if (!control_req)
432 return AE_TYPE; 384 return AE_TYPE;
433 385
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index cb4283f5a79d..41731236f9a1 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -353,7 +353,7 @@ static int acpi_processor_info_open_fs(struct inode *inode, struct file *file)
353 PDE(inode)->data); 353 PDE(inode)->data);
354} 354}
355 355
356static int acpi_processor_add_fs(struct acpi_device *device) 356static int __cpuinit acpi_processor_add_fs(struct acpi_device *device)
357{ 357{
358 struct proc_dir_entry *entry = NULL; 358 struct proc_dir_entry *entry = NULL;
359 359
@@ -722,7 +722,7 @@ static void acpi_processor_notify(struct acpi_device *device, u32 event)
722 switch (event) { 722 switch (event) {
723 case ACPI_PROCESSOR_NOTIFY_PERFORMANCE: 723 case ACPI_PROCESSOR_NOTIFY_PERFORMANCE:
724 saved = pr->performance_platform_limit; 724 saved = pr->performance_platform_limit;
725 acpi_processor_ppc_has_changed(pr); 725 acpi_processor_ppc_has_changed(pr, 1);
726 if (saved == pr->performance_platform_limit) 726 if (saved == pr->performance_platform_limit)
727 break; 727 break;
728 acpi_bus_generate_proc_event(device, event, 728 acpi_bus_generate_proc_event(device, event,
@@ -758,7 +758,7 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb,
758 struct acpi_processor *pr = per_cpu(processors, cpu); 758 struct acpi_processor *pr = per_cpu(processors, cpu);
759 759
760 if (action == CPU_ONLINE && pr) { 760 if (action == CPU_ONLINE && pr) {
761 acpi_processor_ppc_has_changed(pr); 761 acpi_processor_ppc_has_changed(pr, 0);
762 acpi_processor_cst_has_changed(pr); 762 acpi_processor_cst_has_changed(pr);
763 acpi_processor_tstate_has_changed(pr); 763 acpi_processor_tstate_has_changed(pr);
764 } 764 }
@@ -830,7 +830,7 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
830 arch_acpi_processor_cleanup_pdc(pr); 830 arch_acpi_processor_cleanup_pdc(pr);
831 831
832#ifdef CONFIG_CPU_FREQ 832#ifdef CONFIG_CPU_FREQ
833 acpi_processor_ppc_has_changed(pr); 833 acpi_processor_ppc_has_changed(pr, 0);
834#endif 834#endif
835 acpi_processor_get_throttling_info(pr); 835 acpi_processor_get_throttling_info(pr);
836 acpi_processor_get_limit_info(pr); 836 acpi_processor_get_limit_info(pr);
@@ -845,7 +845,7 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device)
845 goto err_power_exit; 845 goto err_power_exit;
846 } 846 }
847 847
848 dev_info(&device->dev, "registered as cooling_device%d\n", 848 dev_dbg(&device->dev, "registered as cooling_device%d\n",
849 pr->cdev->id); 849 pr->cdev->id);
850 850
851 result = sysfs_create_link(&device->dev.kobj, 851 result = sysfs_create_link(&device->dev.kobj,
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index bbd066e7f854..d1676b1754d9 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -164,7 +164,7 @@ static void lapic_timer_check_state(int state, struct acpi_processor *pr,
164 pr->power.timer_broadcast_on_state = state; 164 pr->power.timer_broadcast_on_state = state;
165} 165}
166 166
167static void lapic_timer_propagate_broadcast(void *arg) 167static void __lapic_timer_propagate_broadcast(void *arg)
168{ 168{
169 struct acpi_processor *pr = (struct acpi_processor *) arg; 169 struct acpi_processor *pr = (struct acpi_processor *) arg;
170 unsigned long reason; 170 unsigned long reason;
@@ -175,6 +175,12 @@ static void lapic_timer_propagate_broadcast(void *arg)
175 clockevents_notify(reason, &pr->id); 175 clockevents_notify(reason, &pr->id);
176} 176}
177 177
178static void lapic_timer_propagate_broadcast(struct acpi_processor *pr)
179{
180 smp_call_function_single(pr->id, __lapic_timer_propagate_broadcast,
181 (void *)pr, 1);
182}
183
178/* Power(C) State timer broadcast control */ 184/* Power(C) State timer broadcast control */
179static void lapic_timer_state_broadcast(struct acpi_processor *pr, 185static void lapic_timer_state_broadcast(struct acpi_processor *pr,
180 struct acpi_processor_cx *cx, 186 struct acpi_processor_cx *cx,
@@ -638,8 +644,7 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
638 working++; 644 working++;
639 } 645 }
640 646
641 smp_call_function_single(pr->id, lapic_timer_propagate_broadcast, 647 lapic_timer_propagate_broadcast(pr);
642 pr, 1);
643 648
644 return (working); 649 return (working);
645} 650}
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 01e366d2b6fb..2cabadcc4d8c 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -152,15 +152,59 @@ static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
152 return 0; 152 return 0;
153} 153}
154 154
155int acpi_processor_ppc_has_changed(struct acpi_processor *pr) 155#define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80
156/*
157 * acpi_processor_ppc_ost: Notify firmware the _PPC evaluation status
158 * @handle: ACPI processor handle
159 * @status: the status code of _PPC evaluation
160 * 0: success. OSPM is now using the performance state specificed.
161 * 1: failure. OSPM has not changed the number of P-states in use
162 */
163static void acpi_processor_ppc_ost(acpi_handle handle, int status)
164{
165 union acpi_object params[2] = {
166 {.type = ACPI_TYPE_INTEGER,},
167 {.type = ACPI_TYPE_INTEGER,},
168 };
169 struct acpi_object_list arg_list = {2, params};
170 acpi_handle temp;
171
172 params[0].integer.value = ACPI_PROCESSOR_NOTIFY_PERFORMANCE;
173 params[1].integer.value = status;
174
175 /* when there is no _OST , skip it */
176 if (ACPI_FAILURE(acpi_get_handle(handle, "_OST", &temp)))
177 return;
178
179 acpi_evaluate_object(handle, "_OST", &arg_list, NULL);
180 return;
181}
182
183int acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag)
156{ 184{
157 int ret; 185 int ret;
158 186
159 if (ignore_ppc) 187 if (ignore_ppc) {
188 /*
189 * Only when it is notification event, the _OST object
190 * will be evaluated. Otherwise it is skipped.
191 */
192 if (event_flag)
193 acpi_processor_ppc_ost(pr->handle, 1);
160 return 0; 194 return 0;
195 }
161 196
162 ret = acpi_processor_get_platform_limit(pr); 197 ret = acpi_processor_get_platform_limit(pr);
163 198 /*
199 * Only when it is notification event, the _OST object
200 * will be evaluated. Otherwise it is skipped.
201 */
202 if (event_flag) {
203 if (ret < 0)
204 acpi_processor_ppc_ost(pr->handle, 1);
205 else
206 acpi_processor_ppc_ost(pr->handle, 0);
207 }
164 if (ret < 0) 208 if (ret < 0)
165 return (ret); 209 return (ret);
166 else 210 else
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 65f67815902a..9073ada88835 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -1052,6 +1052,13 @@ static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset)
1052 acpi_device_bid(device)); 1052 acpi_device_bid(device));
1053 } 1053 }
1054 seq_puts(seq, "\n"); 1054 seq_puts(seq, "\n");
1055 } else {
1056 seq_printf(seq, "passive (forced):");
1057 if (tz->thermal_zone->forced_passive)
1058 seq_printf(seq, " %i C\n",
1059 tz->thermal_zone->forced_passive / 1000);
1060 else
1061 seq_printf(seq, "<not set>\n");
1055 } 1062 }
1056 1063
1057 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { 1064 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index d2e698096ace..679cd08b80b4 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -64,6 +64,7 @@
64#include <linux/dmi.h> 64#include <linux/dmi.h>
65#include <linux/string.h> 65#include <linux/string.h>
66#include <linux/ctype.h> 66#include <linux/ctype.h>
67#include <linux/pnp.h>
67 68
68#ifdef CONFIG_PPC_OF 69#ifdef CONFIG_PPC_OF
69#include <linux/of_device.h> 70#include <linux/of_device.h>
@@ -1919,7 +1920,7 @@ struct SPMITable {
1919 s8 spmi_id[1]; /* A '\0' terminated array starts here. */ 1920 s8 spmi_id[1]; /* A '\0' terminated array starts here. */
1920}; 1921};
1921 1922
1922static __devinit int try_init_acpi(struct SPMITable *spmi) 1923static __devinit int try_init_spmi(struct SPMITable *spmi)
1923{ 1924{
1924 struct smi_info *info; 1925 struct smi_info *info;
1925 u8 addr_space; 1926 u8 addr_space;
@@ -1940,7 +1941,7 @@ static __devinit int try_init_acpi(struct SPMITable *spmi)
1940 return -ENOMEM; 1941 return -ENOMEM;
1941 } 1942 }
1942 1943
1943 info->addr_source = "ACPI"; 1944 info->addr_source = "SPMI";
1944 1945
1945 /* Figure out the interface type. */ 1946 /* Figure out the interface type. */
1946 switch (spmi->InterfaceType) { 1947 switch (spmi->InterfaceType) {
@@ -2002,7 +2003,7 @@ static __devinit int try_init_acpi(struct SPMITable *spmi)
2002 return 0; 2003 return 0;
2003} 2004}
2004 2005
2005static __devinit void acpi_find_bmc(void) 2006static __devinit void spmi_find_bmc(void)
2006{ 2007{
2007 acpi_status status; 2008 acpi_status status;
2008 struct SPMITable *spmi; 2009 struct SPMITable *spmi;
@@ -2020,9 +2021,106 @@ static __devinit void acpi_find_bmc(void)
2020 if (status != AE_OK) 2021 if (status != AE_OK)
2021 return; 2022 return;
2022 2023
2023 try_init_acpi(spmi); 2024 try_init_spmi(spmi);
2024 } 2025 }
2025} 2026}
2027
2028static int __devinit ipmi_pnp_probe(struct pnp_dev *dev,
2029 const struct pnp_device_id *dev_id)
2030{
2031 struct acpi_device *acpi_dev;
2032 struct smi_info *info;
2033 acpi_handle handle;
2034 acpi_status status;
2035 unsigned long long tmp;
2036
2037 acpi_dev = pnp_acpi_device(dev);
2038 if (!acpi_dev)
2039 return -ENODEV;
2040
2041 info = kzalloc(sizeof(*info), GFP_KERNEL);
2042 if (!info)
2043 return -ENOMEM;
2044
2045 info->addr_source = "ACPI";
2046
2047 handle = acpi_dev->handle;
2048
2049 /* _IFT tells us the interface type: KCS, BT, etc */
2050 status = acpi_evaluate_integer(handle, "_IFT", NULL, &tmp);
2051 if (ACPI_FAILURE(status))
2052 goto err_free;
2053
2054 switch (tmp) {
2055 case 1:
2056 info->si_type = SI_KCS;
2057 break;
2058 case 2:
2059 info->si_type = SI_SMIC;
2060 break;
2061 case 3:
2062 info->si_type = SI_BT;
2063 break;
2064 default:
2065 dev_info(&dev->dev, "unknown interface type %lld\n", tmp);
2066 goto err_free;
2067 }
2068
2069 if (pnp_port_valid(dev, 0)) {
2070 info->io_setup = port_setup;
2071 info->io.addr_type = IPMI_IO_ADDR_SPACE;
2072 info->io.addr_data = pnp_port_start(dev, 0);
2073 } else if (pnp_mem_valid(dev, 0)) {
2074 info->io_setup = mem_setup;
2075 info->io.addr_type = IPMI_MEM_ADDR_SPACE;
2076 info->io.addr_data = pnp_mem_start(dev, 0);
2077 } else {
2078 dev_err(&dev->dev, "no I/O or memory address\n");
2079 goto err_free;
2080 }
2081
2082 info->io.regspacing = DEFAULT_REGSPACING;
2083 info->io.regsize = DEFAULT_REGSPACING;
2084 info->io.regshift = 0;
2085
2086 /* If _GPE exists, use it; otherwise use standard interrupts */
2087 status = acpi_evaluate_integer(handle, "_GPE", NULL, &tmp);
2088 if (ACPI_SUCCESS(status)) {
2089 info->irq = tmp;
2090 info->irq_setup = acpi_gpe_irq_setup;
2091 } else if (pnp_irq_valid(dev, 0)) {
2092 info->irq = pnp_irq(dev, 0);
2093 info->irq_setup = std_irq_setup;
2094 }
2095
2096 info->dev = &acpi_dev->dev;
2097 pnp_set_drvdata(dev, info);
2098
2099 return try_smi_init(info);
2100
2101err_free:
2102 kfree(info);
2103 return -EINVAL;
2104}
2105
2106static void __devexit ipmi_pnp_remove(struct pnp_dev *dev)
2107{
2108 struct smi_info *info = pnp_get_drvdata(dev);
2109
2110 cleanup_one_si(info);
2111}
2112
2113static const struct pnp_device_id pnp_dev_table[] = {
2114 {"IPI0001", 0},
2115 {"", 0},
2116};
2117
2118static struct pnp_driver ipmi_pnp_driver = {
2119 .name = DEVICE_NAME,
2120 .probe = ipmi_pnp_probe,
2121 .remove = __devexit_p(ipmi_pnp_remove),
2122 .id_table = pnp_dev_table,
2123};
2026#endif 2124#endif
2027 2125
2028#ifdef CONFIG_DMI 2126#ifdef CONFIG_DMI
@@ -2202,7 +2300,6 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev,
2202 int rv; 2300 int rv;
2203 int class_type = pdev->class & PCI_ERMC_CLASSCODE_TYPE_MASK; 2301 int class_type = pdev->class & PCI_ERMC_CLASSCODE_TYPE_MASK;
2204 struct smi_info *info; 2302 struct smi_info *info;
2205 int first_reg_offset = 0;
2206 2303
2207 info = kzalloc(sizeof(*info), GFP_KERNEL); 2304 info = kzalloc(sizeof(*info), GFP_KERNEL);
2208 if (!info) 2305 if (!info)
@@ -2241,9 +2338,6 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev,
2241 info->addr_source_cleanup = ipmi_pci_cleanup; 2338 info->addr_source_cleanup = ipmi_pci_cleanup;
2242 info->addr_source_data = pdev; 2339 info->addr_source_data = pdev;
2243 2340
2244 if (pdev->subsystem_vendor == PCI_HP_VENDOR_ID)
2245 first_reg_offset = 1;
2246
2247 if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) { 2341 if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) {
2248 info->io_setup = port_setup; 2342 info->io_setup = port_setup;
2249 info->io.addr_type = IPMI_IO_ADDR_SPACE; 2343 info->io.addr_type = IPMI_IO_ADDR_SPACE;
@@ -3108,7 +3202,10 @@ static __devinit int init_ipmi_si(void)
3108#endif 3202#endif
3109 3203
3110#ifdef CONFIG_ACPI 3204#ifdef CONFIG_ACPI
3111 acpi_find_bmc(); 3205 spmi_find_bmc();
3206#endif
3207#ifdef CONFIG_PNP
3208 pnp_register_driver(&ipmi_pnp_driver);
3112#endif 3209#endif
3113 3210
3114#ifdef CONFIG_PCI 3211#ifdef CONFIG_PCI
@@ -3233,6 +3330,9 @@ static __exit void cleanup_ipmi_si(void)
3233#ifdef CONFIG_PCI 3330#ifdef CONFIG_PCI
3234 pci_unregister_driver(&ipmi_pci_driver); 3331 pci_unregister_driver(&ipmi_pci_driver);
3235#endif 3332#endif
3333#ifdef CONFIG_PNP
3334 pnp_unregister_driver(&ipmi_pnp_driver);
3335#endif
3236 3336
3237#ifdef CONFIG_PPC_OF 3337#ifdef CONFIG_PPC_OF
3238 of_unregister_platform_driver(&ipmi_of_platform_driver); 3338 of_unregister_platform_driver(&ipmi_of_platform_driver);
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 59f4ba1b7034..1a7a9fc50ea1 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -248,19 +248,6 @@ config SGI_GRU_DEBUG
248 This option enables addition debugging code for the SGI GRU driver. If 248 This option enables addition debugging code for the SGI GRU driver. If
249 you are unsure, say N. 249 you are unsure, say N.
250 250
251config DELL_LAPTOP
252 tristate "Dell Laptop Extras (EXPERIMENTAL)"
253 depends on X86
254 depends on DCDBAS
255 depends on EXPERIMENTAL
256 depends on BACKLIGHT_CLASS_DEVICE
257 depends on RFKILL
258 depends on POWER_SUPPLY
259 default n
260 ---help---
261 This driver adds support for rfkill and backlight control to Dell
262 laptops.
263
264config ISL29003 251config ISL29003
265 tristate "Intersil ISL29003 ambient light sensor" 252 tristate "Intersil ISL29003 ambient light sensor"
266 depends on I2C && SYSFS 253 depends on I2C && SYSFS
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 55ca39dea42e..fc5bf9d2a3f3 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -334,6 +334,8 @@ config EEEPC_LAPTOP
334 depends on HOTPLUG_PCI 334 depends on HOTPLUG_PCI
335 select BACKLIGHT_CLASS_DEVICE 335 select BACKLIGHT_CLASS_DEVICE
336 select HWMON 336 select HWMON
337 select LEDS_CLASS
338 select NEW_LEDS
337 ---help--- 339 ---help---
338 This driver supports the Fn-Fx keys on Eee PC laptops. 340 This driver supports the Fn-Fx keys on Eee PC laptops.
339 341
@@ -365,6 +367,18 @@ config ACPI_WMI
365 It is safe to enable this driver even if your DSDT doesn't define 367 It is safe to enable this driver even if your DSDT doesn't define
366 any ACPI-WMI devices. 368 any ACPI-WMI devices.
367 369
370config MSI_WMI
371 tristate "MSI WMI extras"
372 depends on ACPI_WMI
373 depends on INPUT
374 depends on BACKLIGHT_CLASS_DEVICE
375 select INPUT_SPARSEKMAP
376 help
377 Say Y here if you want to support WMI-based hotkeys on MSI laptops.
378
379 To compile this driver as a module, choose M here: the module will
380 be called msi-wmi.
381
368config ACPI_ASUS 382config ACPI_ASUS
369 tristate "ASUS/Medion Laptop Extras (DEPRECATED)" 383 tristate "ASUS/Medion Laptop Extras (DEPRECATED)"
370 depends on ACPI 384 depends on ACPI
@@ -435,4 +449,19 @@ config ACPI_TOSHIBA
435 449
436 If you have a legacy free Toshiba laptop (such as the Libretto L1 450 If you have a legacy free Toshiba laptop (such as the Libretto L1
437 series), say Y. 451 series), say Y.
452
453config TOSHIBA_BT_RFKILL
454 tristate "Toshiba Bluetooth RFKill switch support"
455 depends on ACPI
456 ---help---
457 This driver adds support for Bluetooth events for the RFKill
458 switch on modern Toshiba laptops with full ACPI support and
459 an RFKill switch.
460
461 This driver handles RFKill events for the TOS6205 Bluetooth,
462 and re-enables it when the switch is set back to the 'on'
463 position.
464
465 If you have a modern Toshiba laptop with a Bluetooth and an
466 RFKill switch (such as the Portege R500), say Y.
438endif # X86_PLATFORM_DEVICES 467endif # X86_PLATFORM_DEVICES
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index d1c16210a512..b7474b6a8bf1 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -18,6 +18,8 @@ obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o
18obj-$(CONFIG_PANASONIC_LAPTOP) += panasonic-laptop.o 18obj-$(CONFIG_PANASONIC_LAPTOP) += panasonic-laptop.o
19obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o 19obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o
20obj-$(CONFIG_ACPI_WMI) += wmi.o 20obj-$(CONFIG_ACPI_WMI) += wmi.o
21obj-$(CONFIG_MSI_WMI) += msi-wmi.o
21obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o 22obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o
22obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o 23obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o
23obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o 24obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
25obj-$(CONFIG_TOSHIBA_BT_RFKILL) += toshiba_bluetooth.o
diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c
index be27aa47e810..79b15b9d9cf0 100644
--- a/drivers/platform/x86/acerhdf.c
+++ b/drivers/platform/x86/acerhdf.c
@@ -52,7 +52,7 @@
52 */ 52 */
53#undef START_IN_KERNEL_MODE 53#undef START_IN_KERNEL_MODE
54 54
55#define DRV_VER "0.5.18" 55#define DRV_VER "0.5.20"
56 56
57/* 57/*
58 * According to the Atom N270 datasheet, 58 * According to the Atom N270 datasheet,
@@ -112,12 +112,14 @@ module_param_string(force_product, force_product, 16, 0);
112MODULE_PARM_DESC(force_product, "Force BIOS product and omit BIOS check"); 112MODULE_PARM_DESC(force_product, "Force BIOS product and omit BIOS check");
113 113
114/* 114/*
115 * cmd_off: to switch the fan completely off / to check if the fan is off 115 * cmd_off: to switch the fan completely off
116 * chk_off: to check if the fan is off
116 * cmd_auto: to set the BIOS in control of the fan. The BIOS regulates then 117 * cmd_auto: to set the BIOS in control of the fan. The BIOS regulates then
117 * the fan speed depending on the temperature 118 * the fan speed depending on the temperature
118 */ 119 */
119struct fancmd { 120struct fancmd {
120 u8 cmd_off; 121 u8 cmd_off;
122 u8 chk_off;
121 u8 cmd_auto; 123 u8 cmd_auto;
122}; 124};
123 125
@@ -134,32 +136,41 @@ struct bios_settings_t {
134/* Register addresses and values for different BIOS versions */ 136/* Register addresses and values for different BIOS versions */
135static const struct bios_settings_t bios_tbl[] = { 137static const struct bios_settings_t bios_tbl[] = {
136 /* AOA110 */ 138 /* AOA110 */
137 {"Acer", "AOA110", "v0.3109", 0x55, 0x58, {0x1f, 0x00} }, 139 {"Acer", "AOA110", "v0.3109", 0x55, 0x58, {0x1f, 0x1f, 0x00} },
138 {"Acer", "AOA110", "v0.3114", 0x55, 0x58, {0x1f, 0x00} }, 140 {"Acer", "AOA110", "v0.3114", 0x55, 0x58, {0x1f, 0x1f, 0x00} },
139 {"Acer", "AOA110", "v0.3301", 0x55, 0x58, {0xaf, 0x00} }, 141 {"Acer", "AOA110", "v0.3301", 0x55, 0x58, {0xaf, 0xaf, 0x00} },
140 {"Acer", "AOA110", "v0.3304", 0x55, 0x58, {0xaf, 0x00} }, 142 {"Acer", "AOA110", "v0.3304", 0x55, 0x58, {0xaf, 0xaf, 0x00} },
141 {"Acer", "AOA110", "v0.3305", 0x55, 0x58, {0xaf, 0x00} }, 143 {"Acer", "AOA110", "v0.3305", 0x55, 0x58, {0xaf, 0xaf, 0x00} },
142 {"Acer", "AOA110", "v0.3307", 0x55, 0x58, {0xaf, 0x00} }, 144 {"Acer", "AOA110", "v0.3307", 0x55, 0x58, {0xaf, 0xaf, 0x00} },
143 {"Acer", "AOA110", "v0.3308", 0x55, 0x58, {0x21, 0x00} }, 145 {"Acer", "AOA110", "v0.3308", 0x55, 0x58, {0x21, 0x21, 0x00} },
144 {"Acer", "AOA110", "v0.3309", 0x55, 0x58, {0x21, 0x00} }, 146 {"Acer", "AOA110", "v0.3309", 0x55, 0x58, {0x21, 0x21, 0x00} },
145 {"Acer", "AOA110", "v0.3310", 0x55, 0x58, {0x21, 0x00} }, 147 {"Acer", "AOA110", "v0.3310", 0x55, 0x58, {0x21, 0x21, 0x00} },
146 /* AOA150 */ 148 /* AOA150 */
147 {"Acer", "AOA150", "v0.3114", 0x55, 0x58, {0x20, 0x00} }, 149 {"Acer", "AOA150", "v0.3114", 0x55, 0x58, {0x20, 0x20, 0x00} },
148 {"Acer", "AOA150", "v0.3301", 0x55, 0x58, {0x20, 0x00} }, 150 {"Acer", "AOA150", "v0.3301", 0x55, 0x58, {0x20, 0x20, 0x00} },
149 {"Acer", "AOA150", "v0.3304", 0x55, 0x58, {0x20, 0x00} }, 151 {"Acer", "AOA150", "v0.3304", 0x55, 0x58, {0x20, 0x20, 0x00} },
150 {"Acer", "AOA150", "v0.3305", 0x55, 0x58, {0x20, 0x00} }, 152 {"Acer", "AOA150", "v0.3305", 0x55, 0x58, {0x20, 0x20, 0x00} },
151 {"Acer", "AOA150", "v0.3307", 0x55, 0x58, {0x20, 0x00} }, 153 {"Acer", "AOA150", "v0.3307", 0x55, 0x58, {0x20, 0x20, 0x00} },
152 {"Acer", "AOA150", "v0.3308", 0x55, 0x58, {0x20, 0x00} }, 154 {"Acer", "AOA150", "v0.3308", 0x55, 0x58, {0x20, 0x20, 0x00} },
153 {"Acer", "AOA150", "v0.3309", 0x55, 0x58, {0x20, 0x00} }, 155 {"Acer", "AOA150", "v0.3309", 0x55, 0x58, {0x20, 0x20, 0x00} },
154 {"Acer", "AOA150", "v0.3310", 0x55, 0x58, {0x20, 0x00} }, 156 {"Acer", "AOA150", "v0.3310", 0x55, 0x58, {0x20, 0x20, 0x00} },
157 /* Acer 1410 */
158 {"Acer", "Aspire 1410", "v0.3120", 0x55, 0x58, {0x9e, 0x9e, 0x00} },
155 /* special BIOS / other */ 159 /* special BIOS / other */
156 {"Gateway", "AOA110", "v0.3103", 0x55, 0x58, {0x21, 0x00} }, 160 {"Gateway", "AOA110", "v0.3103", 0x55, 0x58, {0x21, 0x21, 0x00} },
157 {"Gateway", "AOA150", "v0.3103", 0x55, 0x58, {0x20, 0x00} }, 161 {"Gateway", "AOA150", "v0.3103", 0x55, 0x58, {0x20, 0x20, 0x00} },
158 {"Packard Bell", "DOA150", "v0.3104", 0x55, 0x58, {0x21, 0x00} }, 162 {"Gateway ", "LT31 ", "v1.3103 ", 0x55, 0x58,
159 {"Packard Bell", "AOA110", "v0.3105", 0x55, 0x58, {0x21, 0x00} }, 163 {0x10, 0x0f, 0x00} },
160 {"Packard Bell", "AOA150", "v0.3105", 0x55, 0x58, {0x20, 0x00} }, 164 {"Gateway ", "LT31 ", "v1.3201 ", 0x55, 0x58,
165 {0x10, 0x0f, 0x00} },
166 {"Gateway ", "LT31 ", "v1.3302 ", 0x55, 0x58,
167 {0x10, 0x0f, 0x00} },
168 {"Packard Bell", "DOA150", "v0.3104", 0x55, 0x58, {0x21, 0x21, 0x00} },
169 {"Packard Bell", "DOA150", "v0.3105", 0x55, 0x58, {0x20, 0x20, 0x00} },
170 {"Packard Bell", "AOA110", "v0.3105", 0x55, 0x58, {0x21, 0x21, 0x00} },
171 {"Packard Bell", "AOA150", "v0.3105", 0x55, 0x58, {0x20, 0x20, 0x00} },
161 /* pewpew-terminator */ 172 /* pewpew-terminator */
162 {"", "", "", 0, 0, {0, 0} } 173 {"", "", "", 0, 0, {0, 0, 0} }
163}; 174};
164 175
165static const struct bios_settings_t *bios_cfg __read_mostly; 176static const struct bios_settings_t *bios_cfg __read_mostly;
@@ -183,7 +194,7 @@ static int acerhdf_get_fanstate(int *state)
183 if (ec_read(bios_cfg->fanreg, &fan)) 194 if (ec_read(bios_cfg->fanreg, &fan))
184 return -EINVAL; 195 return -EINVAL;
185 196
186 if (fan != bios_cfg->cmd.cmd_off) 197 if (fan != bios_cfg->cmd.chk_off)
187 *state = ACERHDF_FAN_AUTO; 198 *state = ACERHDF_FAN_AUTO;
188 else 199 else
189 *state = ACERHDF_FAN_OFF; 200 *state = ACERHDF_FAN_OFF;
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index b39d2bb3e75b..61a1c7503658 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -221,6 +221,7 @@ static struct asus_hotk *hotk;
221 */ 221 */
222static const struct acpi_device_id asus_device_ids[] = { 222static const struct acpi_device_id asus_device_ids[] = {
223 {"ATK0100", 0}, 223 {"ATK0100", 0},
224 {"ATK0101", 0},
224 {"", 0}, 225 {"", 0},
225}; 226};
226MODULE_DEVICE_TABLE(acpi, asus_device_ids); 227MODULE_DEVICE_TABLE(acpi, asus_device_ids);
@@ -232,6 +233,7 @@ static void asus_hotk_notify(struct acpi_device *device, u32 event);
232static struct acpi_driver asus_hotk_driver = { 233static struct acpi_driver asus_hotk_driver = {
233 .name = ASUS_HOTK_NAME, 234 .name = ASUS_HOTK_NAME,
234 .class = ASUS_HOTK_CLASS, 235 .class = ASUS_HOTK_CLASS,
236 .owner = THIS_MODULE,
235 .ids = asus_device_ids, 237 .ids = asus_device_ids,
236 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, 238 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
237 .ops = { 239 .ops = {
@@ -293,6 +295,11 @@ struct key_entry {
293enum { KE_KEY, KE_END }; 295enum { KE_KEY, KE_END };
294 296
295static struct key_entry asus_keymap[] = { 297static struct key_entry asus_keymap[] = {
298 {KE_KEY, 0x02, KEY_SCREENLOCK},
299 {KE_KEY, 0x05, KEY_WLAN},
300 {KE_KEY, 0x08, KEY_F13},
301 {KE_KEY, 0x17, KEY_ZOOM},
302 {KE_KEY, 0x1f, KEY_BATTERY},
296 {KE_KEY, 0x30, KEY_VOLUMEUP}, 303 {KE_KEY, 0x30, KEY_VOLUMEUP},
297 {KE_KEY, 0x31, KEY_VOLUMEDOWN}, 304 {KE_KEY, 0x31, KEY_VOLUMEDOWN},
298 {KE_KEY, 0x32, KEY_MUTE}, 305 {KE_KEY, 0x32, KEY_MUTE},
@@ -312,8 +319,11 @@ static struct key_entry asus_keymap[] = {
312 {KE_KEY, 0x5F, KEY_WLAN}, 319 {KE_KEY, 0x5F, KEY_WLAN},
313 {KE_KEY, 0x60, KEY_SWITCHVIDEOMODE}, 320 {KE_KEY, 0x60, KEY_SWITCHVIDEOMODE},
314 {KE_KEY, 0x61, KEY_SWITCHVIDEOMODE}, 321 {KE_KEY, 0x61, KEY_SWITCHVIDEOMODE},
315 {KE_KEY, 0x6B, BTN_TOUCH}, /* Lock Mouse */ 322 {KE_KEY, 0x62, KEY_SWITCHVIDEOMODE},
323 {KE_KEY, 0x63, KEY_SWITCHVIDEOMODE},
324 {KE_KEY, 0x6B, KEY_F13}, /* Lock Touchpad */
316 {KE_KEY, 0x82, KEY_CAMERA}, 325 {KE_KEY, 0x82, KEY_CAMERA},
326 {KE_KEY, 0x88, KEY_WLAN },
317 {KE_KEY, 0x8A, KEY_PROG1}, 327 {KE_KEY, 0x8A, KEY_PROG1},
318 {KE_KEY, 0x95, KEY_MEDIA}, 328 {KE_KEY, 0x95, KEY_MEDIA},
319 {KE_KEY, 0x99, KEY_PHONE}, 329 {KE_KEY, 0x99, KEY_PHONE},
@@ -1240,9 +1250,6 @@ static int asus_hotk_add(struct acpi_device *device)
1240{ 1250{
1241 int result; 1251 int result;
1242 1252
1243 if (!device)
1244 return -EINVAL;
1245
1246 pr_notice("Asus Laptop Support version %s\n", 1253 pr_notice("Asus Laptop Support version %s\n",
1247 ASUS_LAPTOP_VERSION); 1254 ASUS_LAPTOP_VERSION);
1248 1255
@@ -1283,8 +1290,8 @@ static int asus_hotk_add(struct acpi_device *device)
1283 hotk->ledd_status = 0xFFF; 1290 hotk->ledd_status = 0xFFF;
1284 1291
1285 /* Set initial values of light sensor and level */ 1292 /* Set initial values of light sensor and level */
1286 hotk->light_switch = 1; /* Default to light sensor disabled */ 1293 hotk->light_switch = 0; /* Default to light sensor disabled */
1287 hotk->light_level = 0; /* level 5 for sensor sensitivity */ 1294 hotk->light_level = 5; /* level 5 for sensor sensitivity */
1288 1295
1289 if (ls_switch_handle) 1296 if (ls_switch_handle)
1290 set_light_sens_switch(hotk->light_switch); 1297 set_light_sens_switch(hotk->light_switch);
@@ -1306,9 +1313,6 @@ end:
1306 1313
1307static int asus_hotk_remove(struct acpi_device *device, int type) 1314static int asus_hotk_remove(struct acpi_device *device, int type)
1308{ 1315{
1309 if (!device || !acpi_driver_data(device))
1310 return -EINVAL;
1311
1312 kfree(hotk->name); 1316 kfree(hotk->name);
1313 kfree(hotk); 1317 kfree(hotk);
1314 1318
@@ -1444,9 +1448,6 @@ static int __init asus_laptop_init(void)
1444{ 1448{
1445 int result; 1449 int result;
1446 1450
1447 if (acpi_disabled)
1448 return -ENODEV;
1449
1450 result = acpi_bus_register_driver(&asus_hotk_driver); 1451 result = acpi_bus_register_driver(&asus_hotk_driver);
1451 if (result < 0) 1452 if (result < 0)
1452 return result; 1453 return result;
diff --git a/drivers/platform/x86/asus_acpi.c b/drivers/platform/x86/asus_acpi.c
index ddf5240ade8c..0c9c53111a22 100644
--- a/drivers/platform/x86/asus_acpi.c
+++ b/drivers/platform/x86/asus_acpi.c
@@ -466,6 +466,7 @@ MODULE_DEVICE_TABLE(acpi, asus_device_ids);
466static struct acpi_driver asus_hotk_driver = { 466static struct acpi_driver asus_hotk_driver = {
467 .name = "asus_acpi", 467 .name = "asus_acpi",
468 .class = ACPI_HOTK_CLASS, 468 .class = ACPI_HOTK_CLASS,
469 .owner = THIS_MODULE,
469 .ids = asus_device_ids, 470 .ids = asus_device_ids,
470 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, 471 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
471 .ops = { 472 .ops = {
@@ -1334,9 +1335,6 @@ static int asus_hotk_add(struct acpi_device *device)
1334 acpi_status status = AE_OK; 1335 acpi_status status = AE_OK;
1335 int result; 1336 int result;
1336 1337
1337 if (!device)
1338 return -EINVAL;
1339
1340 printk(KERN_NOTICE "Asus Laptop ACPI Extras version %s\n", 1338 printk(KERN_NOTICE "Asus Laptop ACPI Extras version %s\n",
1341 ASUS_ACPI_VERSION); 1339 ASUS_ACPI_VERSION);
1342 1340
@@ -1392,9 +1390,6 @@ end:
1392 1390
1393static int asus_hotk_remove(struct acpi_device *device, int type) 1391static int asus_hotk_remove(struct acpi_device *device, int type)
1394{ 1392{
1395 if (!device || !acpi_driver_data(device))
1396 return -EINVAL;
1397
1398 asus_hotk_remove_fs(device); 1393 asus_hotk_remove_fs(device);
1399 1394
1400 kfree(hotk); 1395 kfree(hotk);
@@ -1422,21 +1417,17 @@ static int __init asus_acpi_init(void)
1422{ 1417{
1423 int result; 1418 int result;
1424 1419
1425 if (acpi_disabled) 1420 result = acpi_bus_register_driver(&asus_hotk_driver);
1426 return -ENODEV; 1421 if (result < 0)
1422 return result;
1427 1423
1428 asus_proc_dir = proc_mkdir(PROC_ASUS, acpi_root_dir); 1424 asus_proc_dir = proc_mkdir(PROC_ASUS, acpi_root_dir);
1429 if (!asus_proc_dir) { 1425 if (!asus_proc_dir) {
1430 printk(KERN_ERR "Asus ACPI: Unable to create /proc entry\n"); 1426 printk(KERN_ERR "Asus ACPI: Unable to create /proc entry\n");
1427 acpi_bus_unregister_driver(&asus_hotk_driver);
1431 return -ENODEV; 1428 return -ENODEV;
1432 } 1429 }
1433 1430
1434 result = acpi_bus_register_driver(&asus_hotk_driver);
1435 if (result < 0) {
1436 remove_proc_entry(PROC_ASUS, acpi_root_dir);
1437 return result;
1438 }
1439
1440 /* 1431 /*
1441 * This is a bit of a kludge. We only want this module loaded 1432 * This is a bit of a kludge. We only want this module loaded
1442 * for ASUS systems, but there's currently no way to probe the 1433 * for ASUS systems, but there's currently no way to probe the
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index 74909c4aaeea..3780994dc8f2 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
@@ -58,6 +58,14 @@ static int da_command_code;
58static int da_num_tokens; 58static int da_num_tokens;
59static struct calling_interface_token *da_tokens; 59static struct calling_interface_token *da_tokens;
60 60
61static struct platform_driver platform_driver = {
62 .driver = {
63 .name = "dell-laptop",
64 .owner = THIS_MODULE,
65 }
66};
67
68static struct platform_device *platform_device;
61static struct backlight_device *dell_backlight_device; 69static struct backlight_device *dell_backlight_device;
62static struct rfkill *wifi_rfkill; 70static struct rfkill *wifi_rfkill;
63static struct rfkill *bluetooth_rfkill; 71static struct rfkill *bluetooth_rfkill;
@@ -74,7 +82,7 @@ static const struct dmi_system_id __initdata dell_device_table[] = {
74 { } 82 { }
75}; 83};
76 84
77static void parse_da_table(const struct dmi_header *dm) 85static void __init parse_da_table(const struct dmi_header *dm)
78{ 86{
79 /* Final token is a terminator, so we don't want to copy it */ 87 /* Final token is a terminator, so we don't want to copy it */
80 int tokens = (dm->length-11)/sizeof(struct calling_interface_token)-1; 88 int tokens = (dm->length-11)/sizeof(struct calling_interface_token)-1;
@@ -103,7 +111,7 @@ static void parse_da_table(const struct dmi_header *dm)
103 da_num_tokens += tokens; 111 da_num_tokens += tokens;
104} 112}
105 113
106static void find_tokens(const struct dmi_header *dm, void *dummy) 114static void __init find_tokens(const struct dmi_header *dm, void *dummy)
107{ 115{
108 switch (dm->type) { 116 switch (dm->type) {
109 case 0xd4: /* Indexed IO */ 117 case 0xd4: /* Indexed IO */
@@ -197,8 +205,8 @@ static void dell_rfkill_query(struct rfkill *rfkill, void *data)
197 dell_send_request(&buffer, 17, 11); 205 dell_send_request(&buffer, 17, 11);
198 status = buffer.output[1]; 206 status = buffer.output[1];
199 207
200 if (status & BIT(bit)) 208 rfkill_set_sw_state(rfkill, !!(status & BIT(bit)));
201 rfkill_set_hw_state(rfkill, !!(status & BIT(16))); 209 rfkill_set_hw_state(rfkill, !(status & BIT(16)));
202} 210}
203 211
204static const struct rfkill_ops dell_rfkill_ops = { 212static const struct rfkill_ops dell_rfkill_ops = {
@@ -206,7 +214,7 @@ static const struct rfkill_ops dell_rfkill_ops = {
206 .query = dell_rfkill_query, 214 .query = dell_rfkill_query,
207}; 215};
208 216
209static int dell_setup_rfkill(void) 217static int __init dell_setup_rfkill(void)
210{ 218{
211 struct calling_interface_buffer buffer; 219 struct calling_interface_buffer buffer;
212 int status; 220 int status;
@@ -217,7 +225,8 @@ static int dell_setup_rfkill(void)
217 status = buffer.output[1]; 225 status = buffer.output[1];
218 226
219 if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) { 227 if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) {
220 wifi_rfkill = rfkill_alloc("dell-wifi", NULL, RFKILL_TYPE_WLAN, 228 wifi_rfkill = rfkill_alloc("dell-wifi", &platform_device->dev,
229 RFKILL_TYPE_WLAN,
221 &dell_rfkill_ops, (void *) 1); 230 &dell_rfkill_ops, (void *) 1);
222 if (!wifi_rfkill) { 231 if (!wifi_rfkill) {
223 ret = -ENOMEM; 232 ret = -ENOMEM;
@@ -229,7 +238,8 @@ static int dell_setup_rfkill(void)
229 } 238 }
230 239
231 if ((status & (1<<3|1<<9)) == (1<<3|1<<9)) { 240 if ((status & (1<<3|1<<9)) == (1<<3|1<<9)) {
232 bluetooth_rfkill = rfkill_alloc("dell-bluetooth", NULL, 241 bluetooth_rfkill = rfkill_alloc("dell-bluetooth",
242 &platform_device->dev,
233 RFKILL_TYPE_BLUETOOTH, 243 RFKILL_TYPE_BLUETOOTH,
234 &dell_rfkill_ops, (void *) 2); 244 &dell_rfkill_ops, (void *) 2);
235 if (!bluetooth_rfkill) { 245 if (!bluetooth_rfkill) {
@@ -242,7 +252,9 @@ static int dell_setup_rfkill(void)
242 } 252 }
243 253
244 if ((status & (1<<4|1<<10)) == (1<<4|1<<10)) { 254 if ((status & (1<<4|1<<10)) == (1<<4|1<<10)) {
245 wwan_rfkill = rfkill_alloc("dell-wwan", NULL, RFKILL_TYPE_WWAN, 255 wwan_rfkill = rfkill_alloc("dell-wwan",
256 &platform_device->dev,
257 RFKILL_TYPE_WWAN,
246 &dell_rfkill_ops, (void *) 3); 258 &dell_rfkill_ops, (void *) 3);
247 if (!wwan_rfkill) { 259 if (!wwan_rfkill) {
248 ret = -ENOMEM; 260 ret = -ENOMEM;
@@ -268,6 +280,22 @@ err_wifi:
268 return ret; 280 return ret;
269} 281}
270 282
283static void dell_cleanup_rfkill(void)
284{
285 if (wifi_rfkill) {
286 rfkill_unregister(wifi_rfkill);
287 rfkill_destroy(wifi_rfkill);
288 }
289 if (bluetooth_rfkill) {
290 rfkill_unregister(bluetooth_rfkill);
291 rfkill_destroy(bluetooth_rfkill);
292 }
293 if (wwan_rfkill) {
294 rfkill_unregister(wwan_rfkill);
295 rfkill_destroy(wwan_rfkill);
296 }
297}
298
271static int dell_send_intensity(struct backlight_device *bd) 299static int dell_send_intensity(struct backlight_device *bd)
272{ 300{
273 struct calling_interface_buffer buffer; 301 struct calling_interface_buffer buffer;
@@ -326,11 +354,23 @@ static int __init dell_init(void)
326 return -ENODEV; 354 return -ENODEV;
327 } 355 }
328 356
357 ret = platform_driver_register(&platform_driver);
358 if (ret)
359 goto fail_platform_driver;
360 platform_device = platform_device_alloc("dell-laptop", -1);
361 if (!platform_device) {
362 ret = -ENOMEM;
363 goto fail_platform_device1;
364 }
365 ret = platform_device_add(platform_device);
366 if (ret)
367 goto fail_platform_device2;
368
329 ret = dell_setup_rfkill(); 369 ret = dell_setup_rfkill();
330 370
331 if (ret) { 371 if (ret) {
332 printk(KERN_WARNING "dell-laptop: Unable to setup rfkill\n"); 372 printk(KERN_WARNING "dell-laptop: Unable to setup rfkill\n");
333 goto out; 373 goto fail_rfkill;
334 } 374 }
335 375
336#ifdef CONFIG_ACPI 376#ifdef CONFIG_ACPI
@@ -352,13 +392,13 @@ static int __init dell_init(void)
352 if (max_intensity) { 392 if (max_intensity) {
353 dell_backlight_device = backlight_device_register( 393 dell_backlight_device = backlight_device_register(
354 "dell_backlight", 394 "dell_backlight",
355 NULL, NULL, 395 &platform_device->dev, NULL,
356 &dell_ops); 396 &dell_ops);
357 397
358 if (IS_ERR(dell_backlight_device)) { 398 if (IS_ERR(dell_backlight_device)) {
359 ret = PTR_ERR(dell_backlight_device); 399 ret = PTR_ERR(dell_backlight_device);
360 dell_backlight_device = NULL; 400 dell_backlight_device = NULL;
361 goto out; 401 goto fail_backlight;
362 } 402 }
363 403
364 dell_backlight_device->props.max_brightness = max_intensity; 404 dell_backlight_device->props.max_brightness = max_intensity;
@@ -368,13 +408,16 @@ static int __init dell_init(void)
368 } 408 }
369 409
370 return 0; 410 return 0;
371out: 411
372 if (wifi_rfkill) 412fail_backlight:
373 rfkill_unregister(wifi_rfkill); 413 dell_cleanup_rfkill();
374 if (bluetooth_rfkill) 414fail_rfkill:
375 rfkill_unregister(bluetooth_rfkill); 415 platform_device_del(platform_device);
376 if (wwan_rfkill) 416fail_platform_device2:
377 rfkill_unregister(wwan_rfkill); 417 platform_device_put(platform_device);
418fail_platform_device1:
419 platform_driver_unregister(&platform_driver);
420fail_platform_driver:
378 kfree(da_tokens); 421 kfree(da_tokens);
379 return ret; 422 return ret;
380} 423}
@@ -382,12 +425,7 @@ out:
382static void __exit dell_exit(void) 425static void __exit dell_exit(void)
383{ 426{
384 backlight_device_unregister(dell_backlight_device); 427 backlight_device_unregister(dell_backlight_device);
385 if (wifi_rfkill) 428 dell_cleanup_rfkill();
386 rfkill_unregister(wifi_rfkill);
387 if (bluetooth_rfkill)
388 rfkill_unregister(bluetooth_rfkill);
389 if (wwan_rfkill)
390 rfkill_unregister(wwan_rfkill);
391} 429}
392 430
393module_init(dell_init); 431module_init(dell_init);
diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c
index 0f900cc9fa7a..67f3fe71c509 100644
--- a/drivers/platform/x86/dell-wmi.c
+++ b/drivers/platform/x86/dell-wmi.c
@@ -31,6 +31,7 @@
31#include <acpi/acpi_drivers.h> 31#include <acpi/acpi_drivers.h>
32#include <linux/acpi.h> 32#include <linux/acpi.h>
33#include <linux/string.h> 33#include <linux/string.h>
34#include <linux/dmi.h>
34 35
35MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>"); 36MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
36MODULE_DESCRIPTION("Dell laptop WMI hotkeys driver"); 37MODULE_DESCRIPTION("Dell laptop WMI hotkeys driver");
@@ -38,6 +39,8 @@ MODULE_LICENSE("GPL");
38 39
39#define DELL_EVENT_GUID "9DBB5994-A997-11DA-B012-B622A1EF5492" 40#define DELL_EVENT_GUID "9DBB5994-A997-11DA-B012-B622A1EF5492"
40 41
42static int acpi_video;
43
41MODULE_ALIAS("wmi:"DELL_EVENT_GUID); 44MODULE_ALIAS("wmi:"DELL_EVENT_GUID);
42 45
43struct key_entry { 46struct key_entry {
@@ -54,7 +57,7 @@ enum { KE_KEY, KE_SW, KE_IGNORE, KE_END };
54 * via the keyboard controller so should not be sent again. 57 * via the keyboard controller so should not be sent again.
55 */ 58 */
56 59
57static struct key_entry dell_wmi_keymap[] = { 60static struct key_entry dell_legacy_wmi_keymap[] = {
58 {KE_KEY, 0xe045, KEY_PROG1}, 61 {KE_KEY, 0xe045, KEY_PROG1},
59 {KE_KEY, 0xe009, KEY_EJECTCD}, 62 {KE_KEY, 0xe009, KEY_EJECTCD},
60 63
@@ -72,7 +75,7 @@ static struct key_entry dell_wmi_keymap[] = {
72 75
73 /* The next device is at offset 6, the active devices are at 76 /* The next device is at offset 6, the active devices are at
74 offset 8 and the attached devices at offset 10 */ 77 offset 8 and the attached devices at offset 10 */
75 {KE_KEY, 0xe00b, KEY_DISPLAYTOGGLE}, 78 {KE_KEY, 0xe00b, KEY_SWITCHVIDEOMODE},
76 79
77 {KE_IGNORE, 0xe00c, KEY_KBDILLUMTOGGLE}, 80 {KE_IGNORE, 0xe00c, KEY_KBDILLUMTOGGLE},
78 81
@@ -96,6 +99,47 @@ static struct key_entry dell_wmi_keymap[] = {
96 {KE_END, 0} 99 {KE_END, 0}
97}; 100};
98 101
102static bool dell_new_hk_type;
103
104struct dell_new_keymap_entry {
105 u16 scancode;
106 u16 keycode;
107};
108
109struct dell_hotkey_table {
110 struct dmi_header header;
111 struct dell_new_keymap_entry keymap[];
112
113};
114
115static struct key_entry *dell_new_wmi_keymap;
116
117static u16 bios_to_linux_keycode[256] = {
118
119 KEY_MEDIA, KEY_NEXTSONG, KEY_PLAYPAUSE, KEY_PREVIOUSSONG,
120 KEY_STOPCD, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN,
121 KEY_WWW, KEY_UNKNOWN, KEY_VOLUMEDOWN, KEY_MUTE,
122 KEY_VOLUMEUP, KEY_UNKNOWN, KEY_BATTERY, KEY_EJECTCD,
123 KEY_UNKNOWN, KEY_SLEEP, KEY_PROG1, KEY_BRIGHTNESSDOWN,
124 KEY_BRIGHTNESSUP, KEY_UNKNOWN, KEY_KBDILLUMTOGGLE,
125 KEY_UNKNOWN, KEY_SWITCHVIDEOMODE, KEY_UNKNOWN, KEY_UNKNOWN,
126 KEY_SWITCHVIDEOMODE, KEY_UNKNOWN, KEY_UNKNOWN, KEY_PROG2,
127 KEY_UNKNOWN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
128 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
129 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
130 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
131 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
132 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
133 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
134 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
135 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
136 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
137 KEY_PROG3
138};
139
140
141static struct key_entry *dell_wmi_keymap = dell_legacy_wmi_keymap;
142
99static struct input_dev *dell_wmi_input_dev; 143static struct input_dev *dell_wmi_input_dev;
100 144
101static struct key_entry *dell_wmi_get_entry_by_scancode(int code) 145static struct key_entry *dell_wmi_get_entry_by_scancode(int code)
@@ -164,24 +208,78 @@ static void dell_wmi_notify(u32 value, void *context)
164 obj = (union acpi_object *)response.pointer; 208 obj = (union acpi_object *)response.pointer;
165 209
166 if (obj && obj->type == ACPI_TYPE_BUFFER) { 210 if (obj && obj->type == ACPI_TYPE_BUFFER) {
167 int *buffer = (int *)obj->buffer.pointer; 211 int reported_key;
168 /* 212 u16 *buffer_entry = (u16 *)obj->buffer.pointer;
169 * The upper bytes of the event may contain 213 if (dell_new_hk_type && (buffer_entry[1] != 0x10)) {
170 * additional information, so mask them off for the 214 printk(KERN_INFO "dell-wmi: Received unknown WMI event"
171 * scancode lookup 215 " (0x%x)\n", buffer_entry[1]);
172 */ 216 return;
173 key = dell_wmi_get_entry_by_scancode(buffer[1] & 0xFFFF); 217 }
174 if (key) { 218
219 if (dell_new_hk_type)
220 reported_key = (int)buffer_entry[2];
221 else
222 reported_key = (int)buffer_entry[1] & 0xffff;
223
224 key = dell_wmi_get_entry_by_scancode(reported_key);
225
226 if (!key) {
227 printk(KERN_INFO "dell-wmi: Unknown key %x pressed\n",
228 reported_key);
229 } else if ((key->keycode == KEY_BRIGHTNESSUP ||
230 key->keycode == KEY_BRIGHTNESSDOWN) && acpi_video) {
231 /* Don't report brightness notifications that will also
232 * come via ACPI */
233 return;
234 } else {
175 input_report_key(dell_wmi_input_dev, key->keycode, 1); 235 input_report_key(dell_wmi_input_dev, key->keycode, 1);
176 input_sync(dell_wmi_input_dev); 236 input_sync(dell_wmi_input_dev);
177 input_report_key(dell_wmi_input_dev, key->keycode, 0); 237 input_report_key(dell_wmi_input_dev, key->keycode, 0);
178 input_sync(dell_wmi_input_dev); 238 input_sync(dell_wmi_input_dev);
179 } else if (buffer[1] & 0xFFFF) 239 }
180 printk(KERN_INFO "dell-wmi: Unknown key %x pressed\n",
181 buffer[1] & 0xFFFF);
182 } 240 }
183} 241}
184 242
243
244static void setup_new_hk_map(const struct dmi_header *dm)
245{
246
247 int i;
248 int hotkey_num = (dm->length-4)/sizeof(struct dell_new_keymap_entry);
249 struct dell_hotkey_table *table =
250 container_of(dm, struct dell_hotkey_table, header);
251
252 dell_new_wmi_keymap = kzalloc((hotkey_num+1) *
253 sizeof(struct key_entry), GFP_KERNEL);
254
255 for (i = 0; i < hotkey_num; i++) {
256 dell_new_wmi_keymap[i].type = KE_KEY;
257 dell_new_wmi_keymap[i].code = table->keymap[i].scancode;
258 dell_new_wmi_keymap[i].keycode =
259 (table->keymap[i].keycode > 255) ? 0 :
260 bios_to_linux_keycode[table->keymap[i].keycode];
261 }
262
263 dell_new_wmi_keymap[i].type = KE_END;
264 dell_new_wmi_keymap[i].code = 0;
265 dell_new_wmi_keymap[i].keycode = 0;
266
267 dell_wmi_keymap = dell_new_wmi_keymap;
268
269}
270
271
272static void find_hk_type(const struct dmi_header *dm, void *dummy)
273{
274
275 if ((dm->type == 0xb2) && (dm->length > 6)) {
276 dell_new_hk_type = true;
277 setup_new_hk_map(dm);
278 }
279
280}
281
282
185static int __init dell_wmi_input_setup(void) 283static int __init dell_wmi_input_setup(void)
186{ 284{
187 struct key_entry *key; 285 struct key_entry *key;
@@ -226,6 +324,9 @@ static int __init dell_wmi_init(void)
226 int err; 324 int err;
227 325
228 if (wmi_has_guid(DELL_EVENT_GUID)) { 326 if (wmi_has_guid(DELL_EVENT_GUID)) {
327
328 dmi_walk(find_hk_type, NULL);
329
229 err = dell_wmi_input_setup(); 330 err = dell_wmi_input_setup();
230 331
231 if (err) 332 if (err)
@@ -240,6 +341,8 @@ static int __init dell_wmi_init(void)
240 return err; 341 return err;
241 } 342 }
242 343
344 acpi_video = acpi_video_backlight_support();
345
243 } else 346 } else
244 printk(KERN_WARNING "dell-wmi: No known WMI GUID found\n"); 347 printk(KERN_WARNING "dell-wmi: No known WMI GUID found\n");
245 348
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c
index e647a856b9bf..5838c69b2fb3 100644
--- a/drivers/platform/x86/eeepc-laptop.c
+++ b/drivers/platform/x86/eeepc-laptop.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * eepc-laptop.c - Asus Eee PC extras 2 * eeepc-laptop.c - Asus Eee PC extras
3 * 3 *
4 * Based on asus_acpi.c as patched for the Eee PC by Asus: 4 * Based on asus_acpi.c as patched for the Eee PC by Asus:
5 * ftp://ftp.asus.com/pub/ASUS/EeePC/701/ASUS_ACPI_071126.rar 5 * ftp://ftp.asus.com/pub/ASUS/EeePC/701/ASUS_ACPI_071126.rar
@@ -34,20 +34,23 @@
34#include <linux/rfkill.h> 34#include <linux/rfkill.h>
35#include <linux/pci.h> 35#include <linux/pci.h>
36#include <linux/pci_hotplug.h> 36#include <linux/pci_hotplug.h>
37#include <linux/leds.h>
37 38
38#define EEEPC_LAPTOP_VERSION "0.1" 39#define EEEPC_LAPTOP_VERSION "0.1"
40#define EEEPC_LAPTOP_NAME "Eee PC Hotkey Driver"
41#define EEEPC_LAPTOP_FILE "eeepc"
39 42
40#define EEEPC_HOTK_NAME "Eee PC Hotkey Driver" 43#define EEEPC_ACPI_CLASS "hotkey"
41#define EEEPC_HOTK_FILE "eeepc" 44#define EEEPC_ACPI_DEVICE_NAME "Hotkey"
42#define EEEPC_HOTK_CLASS "hotkey" 45#define EEEPC_ACPI_HID "ASUS010"
43#define EEEPC_HOTK_DEVICE_NAME "Hotkey"
44#define EEEPC_HOTK_HID "ASUS010"
45 46
47MODULE_AUTHOR("Corentin Chary, Eric Cooper");
48MODULE_DESCRIPTION(EEEPC_LAPTOP_NAME);
49MODULE_LICENSE("GPL");
46 50
47/* 51/*
48 * Definitions for Asus EeePC 52 * Definitions for Asus EeePC
49 */ 53 */
50#define NOTIFY_WLAN_ON 0x10
51#define NOTIFY_BRN_MIN 0x20 54#define NOTIFY_BRN_MIN 0x20
52#define NOTIFY_BRN_MAX 0x2f 55#define NOTIFY_BRN_MAX 0x2f
53 56
@@ -117,58 +120,6 @@ static const char *cm_setv[] = {
117 NULL, NULL, "PBPS", "TPDS" 120 NULL, NULL, "PBPS", "TPDS"
118}; 121};
119 122
120#define EEEPC_EC "\\_SB.PCI0.SBRG.EC0."
121
122#define EEEPC_EC_FAN_PWM EEEPC_EC "SC02" /* Fan PWM duty cycle (%) */
123#define EEEPC_EC_SC02 0x63
124#define EEEPC_EC_FAN_HRPM EEEPC_EC "SC05" /* High byte, fan speed (RPM) */
125#define EEEPC_EC_FAN_LRPM EEEPC_EC "SC06" /* Low byte, fan speed (RPM) */
126#define EEEPC_EC_FAN_CTRL EEEPC_EC "SFB3" /* Byte containing SF25 */
127#define EEEPC_EC_SFB3 0xD3
128
129/*
130 * This is the main structure, we can use it to store useful information
131 * about the hotk device
132 */
133struct eeepc_hotk {
134 struct acpi_device *device; /* the device we are in */
135 acpi_handle handle; /* the handle of the hotk device */
136 u32 cm_supported; /* the control methods supported
137 by this BIOS */
138 uint init_flag; /* Init flags */
139 u16 event_count[128]; /* count for each event */
140 struct input_dev *inputdev;
141 u16 *keycode_map;
142 struct rfkill *wlan_rfkill;
143 struct rfkill *bluetooth_rfkill;
144 struct rfkill *wwan3g_rfkill;
145 struct rfkill *wimax_rfkill;
146 struct hotplug_slot *hotplug_slot;
147 struct mutex hotplug_lock;
148};
149
150/* The actual device the driver binds to */
151static struct eeepc_hotk *ehotk;
152
153/* Platform device/driver */
154static int eeepc_hotk_thaw(struct device *device);
155static int eeepc_hotk_restore(struct device *device);
156
157static const struct dev_pm_ops eeepc_pm_ops = {
158 .thaw = eeepc_hotk_thaw,
159 .restore = eeepc_hotk_restore,
160};
161
162static struct platform_driver platform_driver = {
163 .driver = {
164 .name = EEEPC_HOTK_FILE,
165 .owner = THIS_MODULE,
166 .pm = &eeepc_pm_ops,
167 }
168};
169
170static struct platform_device *platform_device;
171
172struct key_entry { 123struct key_entry {
173 char type; 124 char type;
174 u8 code; 125 u8 code;
@@ -177,7 +128,7 @@ struct key_entry {
177 128
178enum { KE_KEY, KE_END }; 129enum { KE_KEY, KE_END };
179 130
180static struct key_entry eeepc_keymap[] = { 131static const struct key_entry eeepc_keymap[] = {
181 /* Sleep already handled via generic ACPI code */ 132 /* Sleep already handled via generic ACPI code */
182 {KE_KEY, 0x10, KEY_WLAN }, 133 {KE_KEY, 0x10, KEY_WLAN },
183 {KE_KEY, 0x11, KEY_WLAN }, 134 {KE_KEY, 0x11, KEY_WLAN },
@@ -185,77 +136,56 @@ static struct key_entry eeepc_keymap[] = {
185 {KE_KEY, 0x13, KEY_MUTE }, 136 {KE_KEY, 0x13, KEY_MUTE },
186 {KE_KEY, 0x14, KEY_VOLUMEDOWN }, 137 {KE_KEY, 0x14, KEY_VOLUMEDOWN },
187 {KE_KEY, 0x15, KEY_VOLUMEUP }, 138 {KE_KEY, 0x15, KEY_VOLUMEUP },
139 {KE_KEY, 0x16, KEY_DISPLAY_OFF },
188 {KE_KEY, 0x1a, KEY_COFFEE }, 140 {KE_KEY, 0x1a, KEY_COFFEE },
189 {KE_KEY, 0x1b, KEY_ZOOM }, 141 {KE_KEY, 0x1b, KEY_ZOOM },
190 {KE_KEY, 0x1c, KEY_PROG2 }, 142 {KE_KEY, 0x1c, KEY_PROG2 },
191 {KE_KEY, 0x1d, KEY_PROG3 }, 143 {KE_KEY, 0x1d, KEY_PROG3 },
192 {KE_KEY, NOTIFY_BRN_MIN, KEY_BRIGHTNESSDOWN }, 144 {KE_KEY, NOTIFY_BRN_MIN, KEY_BRIGHTNESSDOWN },
193 {KE_KEY, NOTIFY_BRN_MIN + 2, KEY_BRIGHTNESSUP }, 145 {KE_KEY, NOTIFY_BRN_MAX, KEY_BRIGHTNESSUP },
194 {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE }, 146 {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE },
195 {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE }, 147 {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE },
196 {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE }, 148 {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE },
149 {KE_KEY, 0x37, KEY_F13 }, /* Disable Touchpad */
150 {KE_KEY, 0x38, KEY_F14 },
197 {KE_END, 0}, 151 {KE_END, 0},
198}; 152};
199 153
154
200/* 155/*
201 * The hotkey driver declaration 156 * This is the main structure, we can use it to store useful information
202 */ 157 */
203static int eeepc_hotk_add(struct acpi_device *device); 158struct eeepc_laptop {
204static int eeepc_hotk_remove(struct acpi_device *device, int type); 159 acpi_handle handle; /* the handle of the acpi device */
205static void eeepc_hotk_notify(struct acpi_device *device, u32 event); 160 u32 cm_supported; /* the control methods supported
206 161 by this BIOS */
207static const struct acpi_device_id eeepc_device_ids[] = { 162 u16 event_count[128]; /* count for each event */
208 {EEEPC_HOTK_HID, 0},
209 {"", 0},
210};
211MODULE_DEVICE_TABLE(acpi, eeepc_device_ids);
212
213static struct acpi_driver eeepc_hotk_driver = {
214 .name = EEEPC_HOTK_NAME,
215 .class = EEEPC_HOTK_CLASS,
216 .ids = eeepc_device_ids,
217 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
218 .ops = {
219 .add = eeepc_hotk_add,
220 .remove = eeepc_hotk_remove,
221 .notify = eeepc_hotk_notify,
222 },
223};
224 163
225/* PCI hotplug ops */ 164 struct platform_device *platform_device;
226static int eeepc_get_adapter_status(struct hotplug_slot *slot, u8 *value); 165 struct device *hwmon_device;
166 struct backlight_device *backlight_device;
227 167
228static struct hotplug_slot_ops eeepc_hotplug_slot_ops = { 168 struct input_dev *inputdev;
229 .owner = THIS_MODULE, 169 struct key_entry *keymap;
230 .get_adapter_status = eeepc_get_adapter_status,
231 .get_power_status = eeepc_get_adapter_status,
232};
233 170
234/* The backlight device /sys/class/backlight */ 171 struct rfkill *wlan_rfkill;
235static struct backlight_device *eeepc_backlight_device; 172 struct rfkill *bluetooth_rfkill;
173 struct rfkill *wwan3g_rfkill;
174 struct rfkill *wimax_rfkill;
236 175
237/* The hwmon device */ 176 struct hotplug_slot *hotplug_slot;
238static struct device *eeepc_hwmon_device; 177 struct mutex hotplug_lock;
239 178
240/* 179 struct led_classdev tpd_led;
241 * The backlight class declaration 180 int tpd_led_wk;
242 */ 181 struct workqueue_struct *led_workqueue;
243static int read_brightness(struct backlight_device *bd); 182 struct work_struct tpd_led_work;
244static int update_bl_status(struct backlight_device *bd);
245static struct backlight_ops eeepcbl_ops = {
246 .get_brightness = read_brightness,
247 .update_status = update_bl_status,
248}; 183};
249 184
250MODULE_AUTHOR("Corentin Chary, Eric Cooper");
251MODULE_DESCRIPTION(EEEPC_HOTK_NAME);
252MODULE_LICENSE("GPL");
253
254/* 185/*
255 * ACPI Helpers 186 * ACPI Helpers
256 */ 187 */
257static int write_acpi_int(acpi_handle handle, const char *method, int val, 188static int write_acpi_int(acpi_handle handle, const char *method, int val)
258 struct acpi_buffer *output)
259{ 189{
260 struct acpi_object_list params; 190 struct acpi_object_list params;
261 union acpi_object in_obj; 191 union acpi_object in_obj;
@@ -266,7 +196,7 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val,
266 in_obj.type = ACPI_TYPE_INTEGER; 196 in_obj.type = ACPI_TYPE_INTEGER;
267 in_obj.integer.value = val; 197 in_obj.integer.value = val;
268 198
269 status = acpi_evaluate_object(handle, (char *)method, &params, output); 199 status = acpi_evaluate_object(handle, (char *)method, &params, NULL);
270 return (status == AE_OK ? 0 : -1); 200 return (status == AE_OK ? 0 : -1);
271} 201}
272 202
@@ -285,81 +215,56 @@ static int read_acpi_int(acpi_handle handle, const char *method, int *val)
285 } 215 }
286} 216}
287 217
288static int set_acpi(int cm, int value) 218static int set_acpi(struct eeepc_laptop *eeepc, int cm, int value)
289{ 219{
290 if (ehotk->cm_supported & (0x1 << cm)) { 220 const char *method = cm_setv[cm];
291 const char *method = cm_setv[cm];
292 if (method == NULL)
293 return -ENODEV;
294 if (write_acpi_int(ehotk->handle, method, value, NULL))
295 pr_warning("Error writing %s\n", method);
296 }
297 return 0;
298}
299 221
300static int get_acpi(int cm) 222 if (method == NULL)
301{ 223 return -ENODEV;
302 int value = -ENODEV; 224 if ((eeepc->cm_supported & (0x1 << cm)) == 0)
303 if ((ehotk->cm_supported & (0x1 << cm))) { 225 return -ENODEV;
304 const char *method = cm_getv[cm];
305 if (method == NULL)
306 return -ENODEV;
307 if (read_acpi_int(ehotk->handle, method, &value))
308 pr_warning("Error reading %s\n", method);
309 }
310 return value;
311}
312
313/*
314 * Backlight
315 */
316static int read_brightness(struct backlight_device *bd)
317{
318 return get_acpi(CM_ASL_PANELBRIGHT);
319}
320 226
321static int set_brightness(struct backlight_device *bd, int value) 227 if (write_acpi_int(eeepc->handle, method, value))
322{ 228 pr_warning("Error writing %s\n", method);
323 value = max(0, min(15, value)); 229 return 0;
324 return set_acpi(CM_ASL_PANELBRIGHT, value);
325} 230}
326 231
327static int update_bl_status(struct backlight_device *bd) 232static int get_acpi(struct eeepc_laptop *eeepc, int cm)
328{ 233{
329 return set_brightness(bd, bd->props.brightness); 234 const char *method = cm_getv[cm];
330} 235 int value;
331 236
332/* 237 if (method == NULL)
333 * Rfkill helpers 238 return -ENODEV;
334 */ 239 if ((eeepc->cm_supported & (0x1 << cm)) == 0)
240 return -ENODEV;
335 241
336static bool eeepc_wlan_rfkill_blocked(void) 242 if (read_acpi_int(eeepc->handle, method, &value))
337{ 243 pr_warning("Error reading %s\n", method);
338 if (get_acpi(CM_ASL_WLAN) == 1) 244 return value;
339 return false;
340 return true;
341} 245}
342 246
343static int eeepc_rfkill_set(void *data, bool blocked) 247static int acpi_setter_handle(struct eeepc_laptop *eeepc, int cm,
248 acpi_handle *handle)
344{ 249{
345 unsigned long asl = (unsigned long)data; 250 const char *method = cm_setv[cm];
346 return set_acpi(asl, !blocked); 251 acpi_status status;
347}
348 252
349static const struct rfkill_ops eeepc_rfkill_ops = { 253 if (method == NULL)
350 .set_block = eeepc_rfkill_set, 254 return -ENODEV;
351}; 255 if ((eeepc->cm_supported & (0x1 << cm)) == 0)
256 return -ENODEV;
352 257
353static void __devinit eeepc_enable_camera(void) 258 status = acpi_get_handle(eeepc->handle, (char *)method,
354{ 259 handle);
355 /* 260 if (status != AE_OK) {
356 * If the following call to set_acpi() fails, it's because there's no 261 pr_warning("Error finding %s\n", method);
357 * camera so we can ignore the error. 262 return -ENODEV;
358 */ 263 }
359 if (get_acpi(CM_ASL_CAMERA) == 0) 264 return 0;
360 set_acpi(CM_ASL_CAMERA, 1);
361} 265}
362 266
267
363/* 268/*
364 * Sys helpers 269 * Sys helpers
365 */ 270 */
@@ -372,60 +277,63 @@ static int parse_arg(const char *buf, unsigned long count, int *val)
372 return count; 277 return count;
373} 278}
374 279
375static ssize_t store_sys_acpi(int cm, const char *buf, size_t count) 280static ssize_t store_sys_acpi(struct device *dev, int cm,
281 const char *buf, size_t count)
376{ 282{
283 struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
377 int rv, value; 284 int rv, value;
378 285
379 rv = parse_arg(buf, count, &value); 286 rv = parse_arg(buf, count, &value);
380 if (rv > 0) 287 if (rv > 0)
381 value = set_acpi(cm, value); 288 value = set_acpi(eeepc, cm, value);
382 if (value < 0) 289 if (value < 0)
383 return value; 290 return -EIO;
384 return rv; 291 return rv;
385} 292}
386 293
387static ssize_t show_sys_acpi(int cm, char *buf) 294static ssize_t show_sys_acpi(struct device *dev, int cm, char *buf)
388{ 295{
389 int value = get_acpi(cm); 296 struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
297 int value = get_acpi(eeepc, cm);
390 298
391 if (value < 0) 299 if (value < 0)
392 return value; 300 return -EIO;
393 return sprintf(buf, "%d\n", value); 301 return sprintf(buf, "%d\n", value);
394} 302}
395 303
396#define EEEPC_CREATE_DEVICE_ATTR(_name, _cm) \ 304#define EEEPC_CREATE_DEVICE_ATTR(_name, _mode, _cm) \
397 static ssize_t show_##_name(struct device *dev, \ 305 static ssize_t show_##_name(struct device *dev, \
398 struct device_attribute *attr, \ 306 struct device_attribute *attr, \
399 char *buf) \ 307 char *buf) \
400 { \ 308 { \
401 return show_sys_acpi(_cm, buf); \ 309 return show_sys_acpi(dev, _cm, buf); \
402 } \ 310 } \
403 static ssize_t store_##_name(struct device *dev, \ 311 static ssize_t store_##_name(struct device *dev, \
404 struct device_attribute *attr, \ 312 struct device_attribute *attr, \
405 const char *buf, size_t count) \ 313 const char *buf, size_t count) \
406 { \ 314 { \
407 return store_sys_acpi(_cm, buf, count); \ 315 return store_sys_acpi(dev, _cm, buf, count); \
408 } \ 316 } \
409 static struct device_attribute dev_attr_##_name = { \ 317 static struct device_attribute dev_attr_##_name = { \
410 .attr = { \ 318 .attr = { \
411 .name = __stringify(_name), \ 319 .name = __stringify(_name), \
412 .mode = 0644 }, \ 320 .mode = _mode }, \
413 .show = show_##_name, \ 321 .show = show_##_name, \
414 .store = store_##_name, \ 322 .store = store_##_name, \
415 } 323 }
416 324
417EEEPC_CREATE_DEVICE_ATTR(camera, CM_ASL_CAMERA); 325EEEPC_CREATE_DEVICE_ATTR(camera, 0644, CM_ASL_CAMERA);
418EEEPC_CREATE_DEVICE_ATTR(cardr, CM_ASL_CARDREADER); 326EEEPC_CREATE_DEVICE_ATTR(cardr, 0644, CM_ASL_CARDREADER);
419EEEPC_CREATE_DEVICE_ATTR(disp, CM_ASL_DISPLAYSWITCH); 327EEEPC_CREATE_DEVICE_ATTR(disp, 0200, CM_ASL_DISPLAYSWITCH);
420 328
421struct eeepc_cpufv { 329struct eeepc_cpufv {
422 int num; 330 int num;
423 int cur; 331 int cur;
424}; 332};
425 333
426static int get_cpufv(struct eeepc_cpufv *c) 334static int get_cpufv(struct eeepc_laptop *eeepc, struct eeepc_cpufv *c)
427{ 335{
428 c->cur = get_acpi(CM_ASL_CPUFV); 336 c->cur = get_acpi(eeepc, CM_ASL_CPUFV);
429 c->num = (c->cur >> 8) & 0xff; 337 c->num = (c->cur >> 8) & 0xff;
430 c->cur &= 0xff; 338 c->cur &= 0xff;
431 if (c->cur < 0 || c->num <= 0 || c->num > 12) 339 if (c->cur < 0 || c->num <= 0 || c->num > 12)
@@ -437,11 +345,12 @@ static ssize_t show_available_cpufv(struct device *dev,
437 struct device_attribute *attr, 345 struct device_attribute *attr,
438 char *buf) 346 char *buf)
439{ 347{
348 struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
440 struct eeepc_cpufv c; 349 struct eeepc_cpufv c;
441 int i; 350 int i;
442 ssize_t len = 0; 351 ssize_t len = 0;
443 352
444 if (get_cpufv(&c)) 353 if (get_cpufv(eeepc, &c))
445 return -ENODEV; 354 return -ENODEV;
446 for (i = 0; i < c.num; i++) 355 for (i = 0; i < c.num; i++)
447 len += sprintf(buf + len, "%d ", i); 356 len += sprintf(buf + len, "%d ", i);
@@ -453,9 +362,10 @@ static ssize_t show_cpufv(struct device *dev,
453 struct device_attribute *attr, 362 struct device_attribute *attr,
454 char *buf) 363 char *buf)
455{ 364{
365 struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
456 struct eeepc_cpufv c; 366 struct eeepc_cpufv c;
457 367
458 if (get_cpufv(&c)) 368 if (get_cpufv(eeepc, &c))
459 return -ENODEV; 369 return -ENODEV;
460 return sprintf(buf, "%#x\n", (c.num << 8) | c.cur); 370 return sprintf(buf, "%#x\n", (c.num << 8) | c.cur);
461} 371}
@@ -464,17 +374,18 @@ static ssize_t store_cpufv(struct device *dev,
464 struct device_attribute *attr, 374 struct device_attribute *attr,
465 const char *buf, size_t count) 375 const char *buf, size_t count)
466{ 376{
377 struct eeepc_laptop *eeepc = dev_get_drvdata(dev);
467 struct eeepc_cpufv c; 378 struct eeepc_cpufv c;
468 int rv, value; 379 int rv, value;
469 380
470 if (get_cpufv(&c)) 381 if (get_cpufv(eeepc, &c))
471 return -ENODEV; 382 return -ENODEV;
472 rv = parse_arg(buf, count, &value); 383 rv = parse_arg(buf, count, &value);
473 if (rv < 0) 384 if (rv < 0)
474 return rv; 385 return rv;
475 if (!rv || value < 0 || value >= c.num) 386 if (!rv || value < 0 || value >= c.num)
476 return -EINVAL; 387 return -EINVAL;
477 set_acpi(CM_ASL_CPUFV, value); 388 set_acpi(eeepc, CM_ASL_CPUFV, value);
478 return rv; 389 return rv;
479} 390}
480 391
@@ -506,156 +417,125 @@ static struct attribute_group platform_attribute_group = {
506 .attrs = platform_attributes 417 .attrs = platform_attributes
507}; 418};
508 419
509/* 420static int eeepc_platform_init(struct eeepc_laptop *eeepc)
510 * Hotkey functions
511 */
512static struct key_entry *eepc_get_entry_by_scancode(int code)
513{ 421{
514 struct key_entry *key; 422 int result;
515
516 for (key = eeepc_keymap; key->type != KE_END; key++)
517 if (code == key->code)
518 return key;
519 423
520 return NULL; 424 eeepc->platform_device = platform_device_alloc(EEEPC_LAPTOP_FILE, -1);
521} 425 if (!eeepc->platform_device)
426 return -ENOMEM;
427 platform_set_drvdata(eeepc->platform_device, eeepc);
522 428
523static struct key_entry *eepc_get_entry_by_keycode(int code) 429 result = platform_device_add(eeepc->platform_device);
524{ 430 if (result)
525 struct key_entry *key; 431 goto fail_platform_device;
526 432
527 for (key = eeepc_keymap; key->type != KE_END; key++) 433 result = sysfs_create_group(&eeepc->platform_device->dev.kobj,
528 if (code == key->keycode && key->type == KE_KEY) 434 &platform_attribute_group);
529 return key; 435 if (result)
436 goto fail_sysfs;
437 return 0;
530 438
531 return NULL; 439fail_sysfs:
440 platform_device_del(eeepc->platform_device);
441fail_platform_device:
442 platform_device_put(eeepc->platform_device);
443 return result;
532} 444}
533 445
534static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode) 446static void eeepc_platform_exit(struct eeepc_laptop *eeepc)
535{ 447{
536 struct key_entry *key = eepc_get_entry_by_scancode(scancode); 448 sysfs_remove_group(&eeepc->platform_device->dev.kobj,
449 &platform_attribute_group);
450 platform_device_unregister(eeepc->platform_device);
451}
537 452
538 if (key && key->type == KE_KEY) { 453/*
539 *keycode = key->keycode; 454 * LEDs
540 return 0; 455 */
541 } 456/*
457 * These functions actually update the LED's, and are called from a
458 * workqueue. By doing this as separate work rather than when the LED
459 * subsystem asks, we avoid messing with the Asus ACPI stuff during a
460 * potentially bad time, such as a timer interrupt.
461 */
462static void tpd_led_update(struct work_struct *work)
463 {
464 struct eeepc_laptop *eeepc;
542 465
543 return -EINVAL; 466 eeepc = container_of(work, struct eeepc_laptop, tpd_led_work);
467
468 set_acpi(eeepc, CM_ASL_TPD, eeepc->tpd_led_wk);
544} 469}
545 470
546static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode) 471static void tpd_led_set(struct led_classdev *led_cdev,
472 enum led_brightness value)
547{ 473{
548 struct key_entry *key; 474 struct eeepc_laptop *eeepc;
549 int old_keycode;
550 475
551 if (keycode < 0 || keycode > KEY_MAX) 476 eeepc = container_of(led_cdev, struct eeepc_laptop, tpd_led);
552 return -EINVAL;
553 477
554 key = eepc_get_entry_by_scancode(scancode); 478 eeepc->tpd_led_wk = (value > 0) ? 1 : 0;
555 if (key && key->type == KE_KEY) { 479 queue_work(eeepc->led_workqueue, &eeepc->tpd_led_work);
556 old_keycode = key->keycode;
557 key->keycode = keycode;
558 set_bit(keycode, dev->keybit);
559 if (!eepc_get_entry_by_keycode(old_keycode))
560 clear_bit(old_keycode, dev->keybit);
561 return 0;
562 }
563
564 return -EINVAL;
565} 480}
566 481
567static void cmsg_quirk(int cm, const char *name) 482static int eeepc_led_init(struct eeepc_laptop *eeepc)
568{ 483{
569 int dummy; 484 int rv;
570 485
571 /* Some BIOSes do not report cm although it is avaliable. 486 if (get_acpi(eeepc, CM_ASL_TPD) == -ENODEV)
572 Check if cm_getv[cm] works and, if yes, assume cm should be set. */ 487 return 0;
573 if (!(ehotk->cm_supported & (1 << cm))
574 && !read_acpi_int(ehotk->handle, cm_getv[cm], &dummy)) {
575 pr_info("%s (%x) not reported by BIOS,"
576 " enabling anyway\n", name, 1 << cm);
577 ehotk->cm_supported |= 1 << cm;
578 }
579}
580 488
581static void cmsg_quirks(void) 489 eeepc->led_workqueue = create_singlethread_workqueue("led_workqueue");
582{ 490 if (!eeepc->led_workqueue)
583 cmsg_quirk(CM_ASL_LID, "LID"); 491 return -ENOMEM;
584 cmsg_quirk(CM_ASL_TYPE, "TYPE"); 492 INIT_WORK(&eeepc->tpd_led_work, tpd_led_update);
585 cmsg_quirk(CM_ASL_PANELPOWER, "PANELPOWER");
586 cmsg_quirk(CM_ASL_TPD, "TPD");
587}
588 493
589static int eeepc_hotk_check(void) 494 eeepc->tpd_led.name = "eeepc::touchpad";
590{ 495 eeepc->tpd_led.brightness_set = tpd_led_set;
591 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 496 eeepc->tpd_led.max_brightness = 1;
592 int result;
593 497
594 result = acpi_bus_get_status(ehotk->device); 498 rv = led_classdev_register(&eeepc->platform_device->dev,
595 if (result) 499 &eeepc->tpd_led);
596 return result; 500 if (rv) {
597 if (ehotk->device->status.present) { 501 destroy_workqueue(eeepc->led_workqueue);
598 if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag, 502 return rv;
599 &buffer)) {
600 pr_err("Hotkey initialization failed\n");
601 return -ENODEV;
602 } else {
603 pr_notice("Hotkey init flags 0x%x\n", ehotk->init_flag);
604 }
605 /* get control methods supported */
606 if (read_acpi_int(ehotk->handle, "CMSG"
607 , &ehotk->cm_supported)) {
608 pr_err("Get control methods supported failed\n");
609 return -ENODEV;
610 } else {
611 cmsg_quirks();
612 pr_info("Get control methods supported: 0x%x\n",
613 ehotk->cm_supported);
614 }
615 } else {
616 pr_err("Hotkey device not present, aborting\n");
617 return -EINVAL;
618 } 503 }
504
619 return 0; 505 return 0;
620} 506}
621 507
622static int notify_brn(void) 508static void eeepc_led_exit(struct eeepc_laptop *eeepc)
623{ 509{
624 /* returns the *previous* brightness, or -1 */ 510 if (eeepc->tpd_led.dev)
625 struct backlight_device *bd = eeepc_backlight_device; 511 led_classdev_unregister(&eeepc->tpd_led);
626 if (bd) { 512 if (eeepc->led_workqueue)
627 int old = bd->props.brightness; 513 destroy_workqueue(eeepc->led_workqueue);
628 backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
629 return old;
630 }
631 return -1;
632} 514}
633 515
634static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
635 u8 *value)
636{
637 int val = get_acpi(CM_ASL_WLAN);
638 516
639 if (val == 1 || val == 0) 517/*
640 *value = val; 518 * PCI hotplug (for wlan rfkill)
641 else 519 */
642 return -EINVAL; 520static bool eeepc_wlan_rfkill_blocked(struct eeepc_laptop *eeepc)
643 521{
644 return 0; 522 if (get_acpi(eeepc, CM_ASL_WLAN) == 1)
523 return false;
524 return true;
645} 525}
646 526
647static void eeepc_rfkill_hotplug(void) 527static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc)
648{ 528{
649 struct pci_dev *dev; 529 struct pci_dev *dev;
650 struct pci_bus *bus; 530 struct pci_bus *bus;
651 bool blocked = eeepc_wlan_rfkill_blocked(); 531 bool blocked = eeepc_wlan_rfkill_blocked(eeepc);
652 532
653 if (ehotk->wlan_rfkill) 533 if (eeepc->wlan_rfkill)
654 rfkill_set_sw_state(ehotk->wlan_rfkill, blocked); 534 rfkill_set_sw_state(eeepc->wlan_rfkill, blocked);
655 535
656 mutex_lock(&ehotk->hotplug_lock); 536 mutex_lock(&eeepc->hotplug_lock);
657 537
658 if (ehotk->hotplug_slot) { 538 if (eeepc->hotplug_slot) {
659 bus = pci_find_bus(0, 1); 539 bus = pci_find_bus(0, 1);
660 if (!bus) { 540 if (!bus) {
661 pr_warning("Unable to find PCI bus 1?\n"); 541 pr_warning("Unable to find PCI bus 1?\n");
@@ -685,69 +565,23 @@ static void eeepc_rfkill_hotplug(void)
685 } 565 }
686 566
687out_unlock: 567out_unlock:
688 mutex_unlock(&ehotk->hotplug_lock); 568 mutex_unlock(&eeepc->hotplug_lock);
689} 569}
690 570
691static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) 571static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
692{ 572{
573 struct eeepc_laptop *eeepc = data;
574
693 if (event != ACPI_NOTIFY_BUS_CHECK) 575 if (event != ACPI_NOTIFY_BUS_CHECK)
694 return; 576 return;
695 577
696 eeepc_rfkill_hotplug(); 578 eeepc_rfkill_hotplug(eeepc);
697} 579}
698 580
699static void eeepc_hotk_notify(struct acpi_device *device, u32 event) 581static int eeepc_register_rfkill_notifier(struct eeepc_laptop *eeepc,
582 char *node)
700{ 583{
701 static struct key_entry *key; 584 acpi_status status;
702 u16 count;
703 int brn = -ENODEV;
704
705 if (!ehotk)
706 return;
707 if (event > ACPI_MAX_SYS_NOTIFY)
708 return;
709 if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX)
710 brn = notify_brn();
711 count = ehotk->event_count[event % 128]++;
712 acpi_bus_generate_proc_event(ehotk->device, event, count);
713 acpi_bus_generate_netlink_event(ehotk->device->pnp.device_class,
714 dev_name(&ehotk->device->dev), event,
715 count);
716 if (ehotk->inputdev) {
717 if (brn != -ENODEV) {
718 /* brightness-change events need special
719 * handling for conversion to key events
720 */
721 if (brn < 0)
722 brn = event;
723 else
724 brn += NOTIFY_BRN_MIN;
725 if (event < brn)
726 event = NOTIFY_BRN_MIN; /* brightness down */
727 else if (event > brn)
728 event = NOTIFY_BRN_MIN + 2; /* ... up */
729 else
730 event = NOTIFY_BRN_MIN + 1; /* ... unchanged */
731 }
732 key = eepc_get_entry_by_scancode(event);
733 if (key) {
734 switch (key->type) {
735 case KE_KEY:
736 input_report_key(ehotk->inputdev, key->keycode,
737 1);
738 input_sync(ehotk->inputdev);
739 input_report_key(ehotk->inputdev, key->keycode,
740 0);
741 input_sync(ehotk->inputdev);
742 break;
743 }
744 }
745 }
746}
747
748static int eeepc_register_rfkill_notifier(char *node)
749{
750 acpi_status status = AE_OK;
751 acpi_handle handle; 585 acpi_handle handle;
752 586
753 status = acpi_get_handle(NULL, node, &handle); 587 status = acpi_get_handle(NULL, node, &handle);
@@ -756,7 +590,7 @@ static int eeepc_register_rfkill_notifier(char *node)
756 status = acpi_install_notify_handler(handle, 590 status = acpi_install_notify_handler(handle,
757 ACPI_SYSTEM_NOTIFY, 591 ACPI_SYSTEM_NOTIFY,
758 eeepc_rfkill_notify, 592 eeepc_rfkill_notify,
759 NULL); 593 eeepc);
760 if (ACPI_FAILURE(status)) 594 if (ACPI_FAILURE(status))
761 pr_warning("Failed to register notify on %s\n", node); 595 pr_warning("Failed to register notify on %s\n", node);
762 } else 596 } else
@@ -765,7 +599,8 @@ static int eeepc_register_rfkill_notifier(char *node)
765 return 0; 599 return 0;
766} 600}
767 601
768static void eeepc_unregister_rfkill_notifier(char *node) 602static void eeepc_unregister_rfkill_notifier(struct eeepc_laptop *eeepc,
603 char *node)
769{ 604{
770 acpi_status status = AE_OK; 605 acpi_status status = AE_OK;
771 acpi_handle handle; 606 acpi_handle handle;
@@ -782,13 +617,33 @@ static void eeepc_unregister_rfkill_notifier(char *node)
782 } 617 }
783} 618}
784 619
620static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot,
621 u8 *value)
622{
623 struct eeepc_laptop *eeepc = hotplug_slot->private;
624 int val = get_acpi(eeepc, CM_ASL_WLAN);
625
626 if (val == 1 || val == 0)
627 *value = val;
628 else
629 return -EINVAL;
630
631 return 0;
632}
633
785static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot) 634static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot)
786{ 635{
787 kfree(hotplug_slot->info); 636 kfree(hotplug_slot->info);
788 kfree(hotplug_slot); 637 kfree(hotplug_slot);
789} 638}
790 639
791static int eeepc_setup_pci_hotplug(void) 640static struct hotplug_slot_ops eeepc_hotplug_slot_ops = {
641 .owner = THIS_MODULE,
642 .get_adapter_status = eeepc_get_adapter_status,
643 .get_power_status = eeepc_get_adapter_status,
644};
645
646static int eeepc_setup_pci_hotplug(struct eeepc_laptop *eeepc)
792{ 647{
793 int ret = -ENOMEM; 648 int ret = -ENOMEM;
794 struct pci_bus *bus = pci_find_bus(0, 1); 649 struct pci_bus *bus = pci_find_bus(0, 1);
@@ -798,22 +653,22 @@ static int eeepc_setup_pci_hotplug(void)
798 return -ENODEV; 653 return -ENODEV;
799 } 654 }
800 655
801 ehotk->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL); 656 eeepc->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
802 if (!ehotk->hotplug_slot) 657 if (!eeepc->hotplug_slot)
803 goto error_slot; 658 goto error_slot;
804 659
805 ehotk->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info), 660 eeepc->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info),
806 GFP_KERNEL); 661 GFP_KERNEL);
807 if (!ehotk->hotplug_slot->info) 662 if (!eeepc->hotplug_slot->info)
808 goto error_info; 663 goto error_info;
809 664
810 ehotk->hotplug_slot->private = ehotk; 665 eeepc->hotplug_slot->private = eeepc;
811 ehotk->hotplug_slot->release = &eeepc_cleanup_pci_hotplug; 666 eeepc->hotplug_slot->release = &eeepc_cleanup_pci_hotplug;
812 ehotk->hotplug_slot->ops = &eeepc_hotplug_slot_ops; 667 eeepc->hotplug_slot->ops = &eeepc_hotplug_slot_ops;
813 eeepc_get_adapter_status(ehotk->hotplug_slot, 668 eeepc_get_adapter_status(eeepc->hotplug_slot,
814 &ehotk->hotplug_slot->info->adapter_status); 669 &eeepc->hotplug_slot->info->adapter_status);
815 670
816 ret = pci_hp_register(ehotk->hotplug_slot, bus, 0, "eeepc-wifi"); 671 ret = pci_hp_register(eeepc->hotplug_slot, bus, 0, "eeepc-wifi");
817 if (ret) { 672 if (ret) {
818 pr_err("Unable to register hotplug slot - %d\n", ret); 673 pr_err("Unable to register hotplug slot - %d\n", ret);
819 goto error_register; 674 goto error_register;
@@ -822,17 +677,156 @@ static int eeepc_setup_pci_hotplug(void)
822 return 0; 677 return 0;
823 678
824error_register: 679error_register:
825 kfree(ehotk->hotplug_slot->info); 680 kfree(eeepc->hotplug_slot->info);
826error_info: 681error_info:
827 kfree(ehotk->hotplug_slot); 682 kfree(eeepc->hotplug_slot);
828 ehotk->hotplug_slot = NULL; 683 eeepc->hotplug_slot = NULL;
829error_slot: 684error_slot:
830 return ret; 685 return ret;
831} 686}
832 687
688/*
689 * Rfkill devices
690 */
691static int eeepc_rfkill_set(void *data, bool blocked)
692{
693 acpi_handle handle = data;
694
695 return write_acpi_int(handle, NULL, !blocked);
696}
697
698static const struct rfkill_ops eeepc_rfkill_ops = {
699 .set_block = eeepc_rfkill_set,
700};
701
702static int eeepc_new_rfkill(struct eeepc_laptop *eeepc,
703 struct rfkill **rfkill,
704 const char *name,
705 enum rfkill_type type, int cm)
706{
707 acpi_handle handle;
708 int result;
709
710 result = acpi_setter_handle(eeepc, cm, &handle);
711 if (result < 0)
712 return result;
713
714 *rfkill = rfkill_alloc(name, &eeepc->platform_device->dev, type,
715 &eeepc_rfkill_ops, handle);
716
717 if (!*rfkill)
718 return -EINVAL;
719
720 rfkill_init_sw_state(*rfkill, get_acpi(eeepc, cm) != 1);
721 result = rfkill_register(*rfkill);
722 if (result) {
723 rfkill_destroy(*rfkill);
724 *rfkill = NULL;
725 return result;
726 }
727 return 0;
728}
729
730static void eeepc_rfkill_exit(struct eeepc_laptop *eeepc)
731{
732 eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P5");
733 eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P6");
734 eeepc_unregister_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P7");
735 if (eeepc->wlan_rfkill) {
736 rfkill_unregister(eeepc->wlan_rfkill);
737 rfkill_destroy(eeepc->wlan_rfkill);
738 eeepc->wlan_rfkill = NULL;
739 }
740 /*
741 * Refresh pci hotplug in case the rfkill state was changed after
742 * eeepc_unregister_rfkill_notifier()
743 */
744 eeepc_rfkill_hotplug(eeepc);
745 if (eeepc->hotplug_slot)
746 pci_hp_deregister(eeepc->hotplug_slot);
747
748 if (eeepc->bluetooth_rfkill) {
749 rfkill_unregister(eeepc->bluetooth_rfkill);
750 rfkill_destroy(eeepc->bluetooth_rfkill);
751 eeepc->bluetooth_rfkill = NULL;
752 }
753 if (eeepc->wwan3g_rfkill) {
754 rfkill_unregister(eeepc->wwan3g_rfkill);
755 rfkill_destroy(eeepc->wwan3g_rfkill);
756 eeepc->wwan3g_rfkill = NULL;
757 }
758 if (eeepc->wimax_rfkill) {
759 rfkill_unregister(eeepc->wimax_rfkill);
760 rfkill_destroy(eeepc->wimax_rfkill);
761 eeepc->wimax_rfkill = NULL;
762 }
763}
764
765static int eeepc_rfkill_init(struct eeepc_laptop *eeepc)
766{
767 int result = 0;
768
769 mutex_init(&eeepc->hotplug_lock);
770
771 result = eeepc_new_rfkill(eeepc, &eeepc->wlan_rfkill,
772 "eeepc-wlan", RFKILL_TYPE_WLAN,
773 CM_ASL_WLAN);
774
775 if (result && result != -ENODEV)
776 goto exit;
777
778 result = eeepc_new_rfkill(eeepc, &eeepc->bluetooth_rfkill,
779 "eeepc-bluetooth", RFKILL_TYPE_BLUETOOTH,
780 CM_ASL_BLUETOOTH);
781
782 if (result && result != -ENODEV)
783 goto exit;
784
785 result = eeepc_new_rfkill(eeepc, &eeepc->wwan3g_rfkill,
786 "eeepc-wwan3g", RFKILL_TYPE_WWAN,
787 CM_ASL_3G);
788
789 if (result && result != -ENODEV)
790 goto exit;
791
792 result = eeepc_new_rfkill(eeepc, &eeepc->wimax_rfkill,
793 "eeepc-wimax", RFKILL_TYPE_WIMAX,
794 CM_ASL_WIMAX);
795
796 if (result && result != -ENODEV)
797 goto exit;
798
799 result = eeepc_setup_pci_hotplug(eeepc);
800 /*
801 * If we get -EBUSY then something else is handling the PCI hotplug -
802 * don't fail in this case
803 */
804 if (result == -EBUSY)
805 result = 0;
806
807 eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P5");
808 eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P6");
809 eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P7");
810 /*
811 * Refresh pci hotplug in case the rfkill state was changed during
812 * setup.
813 */
814 eeepc_rfkill_hotplug(eeepc);
815
816exit:
817 if (result && result != -ENODEV)
818 eeepc_rfkill_exit(eeepc);
819 return result;
820}
821
822/*
823 * Platform driver - hibernate/resume callbacks
824 */
833static int eeepc_hotk_thaw(struct device *device) 825static int eeepc_hotk_thaw(struct device *device)
834{ 826{
835 if (ehotk->wlan_rfkill) { 827 struct eeepc_laptop *eeepc = dev_get_drvdata(device);
828
829 if (eeepc->wlan_rfkill) {
836 bool wlan; 830 bool wlan;
837 831
838 /* 832 /*
@@ -840,8 +834,8 @@ static int eeepc_hotk_thaw(struct device *device)
840 * during suspend. Normally it restores it on resume, but 834 * during suspend. Normally it restores it on resume, but
841 * we should kick it ourselves in case hibernation is aborted. 835 * we should kick it ourselves in case hibernation is aborted.
842 */ 836 */
843 wlan = get_acpi(CM_ASL_WLAN); 837 wlan = get_acpi(eeepc, CM_ASL_WLAN);
844 set_acpi(CM_ASL_WLAN, wlan); 838 set_acpi(eeepc, CM_ASL_WLAN, wlan);
845 } 839 }
846 840
847 return 0; 841 return 0;
@@ -849,70 +843,96 @@ static int eeepc_hotk_thaw(struct device *device)
849 843
850static int eeepc_hotk_restore(struct device *device) 844static int eeepc_hotk_restore(struct device *device)
851{ 845{
846 struct eeepc_laptop *eeepc = dev_get_drvdata(device);
847
852 /* Refresh both wlan rfkill state and pci hotplug */ 848 /* Refresh both wlan rfkill state and pci hotplug */
853 if (ehotk->wlan_rfkill) 849 if (eeepc->wlan_rfkill)
854 eeepc_rfkill_hotplug(); 850 eeepc_rfkill_hotplug(eeepc);
855 851
856 if (ehotk->bluetooth_rfkill) 852 if (eeepc->bluetooth_rfkill)
857 rfkill_set_sw_state(ehotk->bluetooth_rfkill, 853 rfkill_set_sw_state(eeepc->bluetooth_rfkill,
858 get_acpi(CM_ASL_BLUETOOTH) != 1); 854 get_acpi(eeepc, CM_ASL_BLUETOOTH) != 1);
859 if (ehotk->wwan3g_rfkill) 855 if (eeepc->wwan3g_rfkill)
860 rfkill_set_sw_state(ehotk->wwan3g_rfkill, 856 rfkill_set_sw_state(eeepc->wwan3g_rfkill,
861 get_acpi(CM_ASL_3G) != 1); 857 get_acpi(eeepc, CM_ASL_3G) != 1);
862 if (ehotk->wimax_rfkill) 858 if (eeepc->wimax_rfkill)
863 rfkill_set_sw_state(ehotk->wimax_rfkill, 859 rfkill_set_sw_state(eeepc->wimax_rfkill,
864 get_acpi(CM_ASL_WIMAX) != 1); 860 get_acpi(eeepc, CM_ASL_WIMAX) != 1);
865 861
866 return 0; 862 return 0;
867} 863}
868 864
865static const struct dev_pm_ops eeepc_pm_ops = {
866 .thaw = eeepc_hotk_thaw,
867 .restore = eeepc_hotk_restore,
868};
869
870static struct platform_driver platform_driver = {
871 .driver = {
872 .name = EEEPC_LAPTOP_FILE,
873 .owner = THIS_MODULE,
874 .pm = &eeepc_pm_ops,
875 }
876};
877
869/* 878/*
870 * Hwmon 879 * Hwmon device
871 */ 880 */
881
882#define EEEPC_EC_SC00 0x61
883#define EEEPC_EC_FAN_PWM (EEEPC_EC_SC00 + 2) /* Fan PWM duty cycle (%) */
884#define EEEPC_EC_FAN_HRPM (EEEPC_EC_SC00 + 5) /* High byte, fan speed (RPM) */
885#define EEEPC_EC_FAN_LRPM (EEEPC_EC_SC00 + 6) /* Low byte, fan speed (RPM) */
886
887#define EEEPC_EC_SFB0 0xD0
888#define EEEPC_EC_FAN_CTRL (EEEPC_EC_SFB0 + 3) /* Byte containing SF25 */
889
872static int eeepc_get_fan_pwm(void) 890static int eeepc_get_fan_pwm(void)
873{ 891{
874 int value = 0; 892 u8 value = 0;
875 893
876 read_acpi_int(NULL, EEEPC_EC_FAN_PWM, &value); 894 ec_read(EEEPC_EC_FAN_PWM, &value);
877 value = value * 255 / 100; 895 return value * 255 / 100;
878 return (value);
879} 896}
880 897
881static void eeepc_set_fan_pwm(int value) 898static void eeepc_set_fan_pwm(int value)
882{ 899{
883 value = SENSORS_LIMIT(value, 0, 255); 900 value = SENSORS_LIMIT(value, 0, 255);
884 value = value * 100 / 255; 901 value = value * 100 / 255;
885 ec_write(EEEPC_EC_SC02, value); 902 ec_write(EEEPC_EC_FAN_PWM, value);
886} 903}
887 904
888static int eeepc_get_fan_rpm(void) 905static int eeepc_get_fan_rpm(void)
889{ 906{
890 int high = 0; 907 u8 high = 0;
891 int low = 0; 908 u8 low = 0;
892 909
893 read_acpi_int(NULL, EEEPC_EC_FAN_HRPM, &high); 910 ec_read(EEEPC_EC_FAN_HRPM, &high);
894 read_acpi_int(NULL, EEEPC_EC_FAN_LRPM, &low); 911 ec_read(EEEPC_EC_FAN_LRPM, &low);
895 return (high << 8 | low); 912 return high << 8 | low;
896} 913}
897 914
898static int eeepc_get_fan_ctrl(void) 915static int eeepc_get_fan_ctrl(void)
899{ 916{
900 int value = 0; 917 u8 value = 0;
901 918
902 read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value); 919 ec_read(EEEPC_EC_FAN_CTRL, &value);
903 return ((value & 0x02 ? 1 : 0)); 920 if (value & 0x02)
921 return 1; /* manual */
922 else
923 return 2; /* automatic */
904} 924}
905 925
906static void eeepc_set_fan_ctrl(int manual) 926static void eeepc_set_fan_ctrl(int manual)
907{ 927{
908 int value = 0; 928 u8 value = 0;
909 929
910 read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value); 930 ec_read(EEEPC_EC_FAN_CTRL, &value);
911 if (manual) 931 if (manual == 1)
912 value |= 0x02; 932 value |= 0x02;
913 else 933 else
914 value &= ~0x02; 934 value &= ~0x02;
915 ec_write(EEEPC_EC_SFB3, value); 935 ec_write(EEEPC_EC_FAN_CTRL, value);
916} 936}
917 937
918static ssize_t store_sys_hwmon(void (*set)(int), const char *buf, size_t count) 938static ssize_t store_sys_hwmon(void (*set)(int), const char *buf, size_t count)
@@ -970,348 +990,485 @@ static struct attribute_group hwmon_attribute_group = {
970 .attrs = hwmon_attributes 990 .attrs = hwmon_attributes
971}; 991};
972 992
973/* 993static void eeepc_hwmon_exit(struct eeepc_laptop *eeepc)
974 * exit/init
975 */
976static void eeepc_backlight_exit(void)
977{ 994{
978 if (eeepc_backlight_device) 995 struct device *hwmon;
979 backlight_device_unregister(eeepc_backlight_device); 996
980 eeepc_backlight_device = NULL; 997 hwmon = eeepc->hwmon_device;
998 if (!hwmon)
999 return;
1000 sysfs_remove_group(&hwmon->kobj,
1001 &hwmon_attribute_group);
1002 hwmon_device_unregister(hwmon);
1003 eeepc->hwmon_device = NULL;
981} 1004}
982 1005
983static void eeepc_rfkill_exit(void) 1006static int eeepc_hwmon_init(struct eeepc_laptop *eeepc)
984{ 1007{
985 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P5"); 1008 struct device *hwmon;
986 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); 1009 int result;
987 eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); 1010
988 if (ehotk->wlan_rfkill) { 1011 hwmon = hwmon_device_register(&eeepc->platform_device->dev);
989 rfkill_unregister(ehotk->wlan_rfkill); 1012 if (IS_ERR(hwmon)) {
990 rfkill_destroy(ehotk->wlan_rfkill); 1013 pr_err("Could not register eeepc hwmon device\n");
991 ehotk->wlan_rfkill = NULL; 1014 eeepc->hwmon_device = NULL;
992 } 1015 return PTR_ERR(hwmon);
993 /*
994 * Refresh pci hotplug in case the rfkill state was changed after
995 * eeepc_unregister_rfkill_notifier()
996 */
997 eeepc_rfkill_hotplug();
998 if (ehotk->hotplug_slot)
999 pci_hp_deregister(ehotk->hotplug_slot);
1000
1001 if (ehotk->bluetooth_rfkill) {
1002 rfkill_unregister(ehotk->bluetooth_rfkill);
1003 rfkill_destroy(ehotk->bluetooth_rfkill);
1004 ehotk->bluetooth_rfkill = NULL;
1005 }
1006 if (ehotk->wwan3g_rfkill) {
1007 rfkill_unregister(ehotk->wwan3g_rfkill);
1008 rfkill_destroy(ehotk->wwan3g_rfkill);
1009 ehotk->wwan3g_rfkill = NULL;
1010 }
1011 if (ehotk->wimax_rfkill) {
1012 rfkill_unregister(ehotk->wimax_rfkill);
1013 rfkill_destroy(ehotk->wimax_rfkill);
1014 ehotk->wimax_rfkill = NULL;
1015 } 1016 }
1017 eeepc->hwmon_device = hwmon;
1018 result = sysfs_create_group(&hwmon->kobj,
1019 &hwmon_attribute_group);
1020 if (result)
1021 eeepc_hwmon_exit(eeepc);
1022 return result;
1016} 1023}
1017 1024
1018static void eeepc_input_exit(void) 1025/*
1026 * Backlight device
1027 */
1028static int read_brightness(struct backlight_device *bd)
1019{ 1029{
1020 if (ehotk->inputdev) 1030 struct eeepc_laptop *eeepc = bl_get_data(bd);
1021 input_unregister_device(ehotk->inputdev); 1031
1032 return get_acpi(eeepc, CM_ASL_PANELBRIGHT);
1022} 1033}
1023 1034
1024static void eeepc_hwmon_exit(void) 1035static int set_brightness(struct backlight_device *bd, int value)
1025{ 1036{
1026 struct device *hwmon; 1037 struct eeepc_laptop *eeepc = bl_get_data(bd);
1027 1038
1028 hwmon = eeepc_hwmon_device; 1039 return set_acpi(eeepc, CM_ASL_PANELBRIGHT, value);
1029 if (!hwmon)
1030 return ;
1031 sysfs_remove_group(&hwmon->kobj,
1032 &hwmon_attribute_group);
1033 hwmon_device_unregister(hwmon);
1034 eeepc_hwmon_device = NULL;
1035} 1040}
1036 1041
1037static int eeepc_new_rfkill(struct rfkill **rfkill, 1042static int update_bl_status(struct backlight_device *bd)
1038 const char *name, struct device *dev,
1039 enum rfkill_type type, int cm)
1040{ 1043{
1041 int result; 1044 return set_brightness(bd, bd->props.brightness);
1045}
1042 1046
1043 result = get_acpi(cm); 1047static struct backlight_ops eeepcbl_ops = {
1044 if (result < 0) 1048 .get_brightness = read_brightness,
1045 return result; 1049 .update_status = update_bl_status,
1050};
1046 1051
1047 *rfkill = rfkill_alloc(name, dev, type, 1052static int eeepc_backlight_notify(struct eeepc_laptop *eeepc)
1048 &eeepc_rfkill_ops, (void *)(unsigned long)cm); 1053{
1054 struct backlight_device *bd = eeepc->backlight_device;
1055 int old = bd->props.brightness;
1049 1056
1050 if (!*rfkill) 1057 backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
1051 return -EINVAL;
1052 1058
1053 rfkill_init_sw_state(*rfkill, get_acpi(cm) != 1); 1059 return old;
1054 result = rfkill_register(*rfkill);
1055 if (result) {
1056 rfkill_destroy(*rfkill);
1057 *rfkill = NULL;
1058 return result;
1059 }
1060 return 0;
1061} 1060}
1062 1061
1063 1062static int eeepc_backlight_init(struct eeepc_laptop *eeepc)
1064static int eeepc_rfkill_init(struct device *dev)
1065{ 1063{
1066 int result = 0; 1064 struct backlight_device *bd;
1067
1068 mutex_init(&ehotk->hotplug_lock);
1069 1065
1070 result = eeepc_new_rfkill(&ehotk->wlan_rfkill, 1066 bd = backlight_device_register(EEEPC_LAPTOP_FILE,
1071 "eeepc-wlan", dev, 1067 &eeepc->platform_device->dev,
1072 RFKILL_TYPE_WLAN, CM_ASL_WLAN); 1068 eeepc, &eeepcbl_ops);
1069 if (IS_ERR(bd)) {
1070 pr_err("Could not register eeepc backlight device\n");
1071 eeepc->backlight_device = NULL;
1072 return PTR_ERR(bd);
1073 }
1074 eeepc->backlight_device = bd;
1075 bd->props.max_brightness = 15;
1076 bd->props.brightness = read_brightness(bd);
1077 bd->props.power = FB_BLANK_UNBLANK;
1078 backlight_update_status(bd);
1079 return 0;
1080}
1073 1081
1074 if (result && result != -ENODEV) 1082static void eeepc_backlight_exit(struct eeepc_laptop *eeepc)
1075 goto exit; 1083{
1084 if (eeepc->backlight_device)
1085 backlight_device_unregister(eeepc->backlight_device);
1086 eeepc->backlight_device = NULL;
1087}
1076 1088
1077 result = eeepc_new_rfkill(&ehotk->bluetooth_rfkill,
1078 "eeepc-bluetooth", dev,
1079 RFKILL_TYPE_BLUETOOTH, CM_ASL_BLUETOOTH);
1080 1089
1081 if (result && result != -ENODEV) 1090/*
1082 goto exit; 1091 * Input device (i.e. hotkeys)
1092 */
1093static struct key_entry *eeepc_get_entry_by_scancode(
1094 struct eeepc_laptop *eeepc,
1095 int code)
1096{
1097 struct key_entry *key;
1083 1098
1084 result = eeepc_new_rfkill(&ehotk->wwan3g_rfkill, 1099 for (key = eeepc->keymap; key->type != KE_END; key++)
1085 "eeepc-wwan3g", dev, 1100 if (code == key->code)
1086 RFKILL_TYPE_WWAN, CM_ASL_3G); 1101 return key;
1087 1102
1088 if (result && result != -ENODEV) 1103 return NULL;
1089 goto exit; 1104}
1090 1105
1091 result = eeepc_new_rfkill(&ehotk->wimax_rfkill, 1106static void eeepc_input_notify(struct eeepc_laptop *eeepc, int event)
1092 "eeepc-wimax", dev, 1107{
1093 RFKILL_TYPE_WIMAX, CM_ASL_WIMAX); 1108 static struct key_entry *key;
1094 1109
1095 if (result && result != -ENODEV) 1110 key = eeepc_get_entry_by_scancode(eeepc, event);
1096 goto exit; 1111 if (key) {
1112 switch (key->type) {
1113 case KE_KEY:
1114 input_report_key(eeepc->inputdev, key->keycode,
1115 1);
1116 input_sync(eeepc->inputdev);
1117 input_report_key(eeepc->inputdev, key->keycode,
1118 0);
1119 input_sync(eeepc->inputdev);
1120 break;
1121 }
1122 }
1123}
1097 1124
1098 result = eeepc_setup_pci_hotplug(); 1125static struct key_entry *eeepc_get_entry_by_keycode(
1099 /* 1126 struct eeepc_laptop *eeepc, int code)
1100 * If we get -EBUSY then something else is handling the PCI hotplug - 1127{
1101 * don't fail in this case 1128 struct key_entry *key;
1102 */
1103 if (result == -EBUSY)
1104 result = 0;
1105 1129
1106 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P5"); 1130 for (key = eeepc->keymap; key->type != KE_END; key++)
1107 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); 1131 if (code == key->keycode && key->type == KE_KEY)
1108 eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); 1132 return key;
1109 /*
1110 * Refresh pci hotplug in case the rfkill state was changed during
1111 * setup.
1112 */
1113 eeepc_rfkill_hotplug();
1114 1133
1115exit: 1134 return NULL;
1116 if (result && result != -ENODEV)
1117 eeepc_rfkill_exit();
1118 return result;
1119} 1135}
1120 1136
1121static int eeepc_backlight_init(struct device *dev) 1137static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode)
1122{ 1138{
1123 struct backlight_device *bd; 1139 struct eeepc_laptop *eeepc = input_get_drvdata(dev);
1140 struct key_entry *key = eeepc_get_entry_by_scancode(eeepc, scancode);
1124 1141
1125 bd = backlight_device_register(EEEPC_HOTK_FILE, dev, 1142 if (key && key->type == KE_KEY) {
1126 NULL, &eeepcbl_ops); 1143 *keycode = key->keycode;
1127 if (IS_ERR(bd)) { 1144 return 0;
1128 pr_err("Could not register eeepc backlight device\n");
1129 eeepc_backlight_device = NULL;
1130 return PTR_ERR(bd);
1131 } 1145 }
1132 eeepc_backlight_device = bd; 1146
1133 bd->props.max_brightness = 15; 1147 return -EINVAL;
1134 bd->props.brightness = read_brightness(NULL);
1135 bd->props.power = FB_BLANK_UNBLANK;
1136 backlight_update_status(bd);
1137 return 0;
1138} 1148}
1139 1149
1140static int eeepc_hwmon_init(struct device *dev) 1150static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode)
1141{ 1151{
1142 struct device *hwmon; 1152 struct eeepc_laptop *eeepc = input_get_drvdata(dev);
1143 int result; 1153 struct key_entry *key;
1154 int old_keycode;
1144 1155
1145 hwmon = hwmon_device_register(dev); 1156 if (keycode < 0 || keycode > KEY_MAX)
1146 if (IS_ERR(hwmon)) { 1157 return -EINVAL;
1147 pr_err("Could not register eeepc hwmon device\n"); 1158
1148 eeepc_hwmon_device = NULL; 1159 key = eeepc_get_entry_by_scancode(eeepc, scancode);
1149 return PTR_ERR(hwmon); 1160 if (key && key->type == KE_KEY) {
1161 old_keycode = key->keycode;
1162 key->keycode = keycode;
1163 set_bit(keycode, dev->keybit);
1164 if (!eeepc_get_entry_by_keycode(eeepc, old_keycode))
1165 clear_bit(old_keycode, dev->keybit);
1166 return 0;
1150 } 1167 }
1151 eeepc_hwmon_device = hwmon; 1168
1152 result = sysfs_create_group(&hwmon->kobj, 1169 return -EINVAL;
1153 &hwmon_attribute_group);
1154 if (result)
1155 eeepc_hwmon_exit();
1156 return result;
1157} 1170}
1158 1171
1159static int eeepc_input_init(struct device *dev) 1172static int eeepc_input_init(struct eeepc_laptop *eeepc)
1160{ 1173{
1161 const struct key_entry *key; 1174 const struct key_entry *key;
1162 int result; 1175 int result;
1163 1176
1164 ehotk->inputdev = input_allocate_device(); 1177 eeepc->inputdev = input_allocate_device();
1165 if (!ehotk->inputdev) { 1178 if (!eeepc->inputdev) {
1166 pr_info("Unable to allocate input device\n"); 1179 pr_info("Unable to allocate input device\n");
1167 return -ENOMEM; 1180 return -ENOMEM;
1168 } 1181 }
1169 ehotk->inputdev->name = "Asus EeePC extra buttons"; 1182 eeepc->inputdev->name = "Asus EeePC extra buttons";
1170 ehotk->inputdev->dev.parent = dev; 1183 eeepc->inputdev->dev.parent = &eeepc->platform_device->dev;
1171 ehotk->inputdev->phys = EEEPC_HOTK_FILE "/input0"; 1184 eeepc->inputdev->phys = EEEPC_LAPTOP_FILE "/input0";
1172 ehotk->inputdev->id.bustype = BUS_HOST; 1185 eeepc->inputdev->id.bustype = BUS_HOST;
1173 ehotk->inputdev->getkeycode = eeepc_getkeycode; 1186 eeepc->inputdev->getkeycode = eeepc_getkeycode;
1174 ehotk->inputdev->setkeycode = eeepc_setkeycode; 1187 eeepc->inputdev->setkeycode = eeepc_setkeycode;
1175 1188 input_set_drvdata(eeepc->inputdev, eeepc);
1189
1190 eeepc->keymap = kmemdup(eeepc_keymap, sizeof(eeepc_keymap),
1191 GFP_KERNEL);
1176 for (key = eeepc_keymap; key->type != KE_END; key++) { 1192 for (key = eeepc_keymap; key->type != KE_END; key++) {
1177 switch (key->type) { 1193 switch (key->type) {
1178 case KE_KEY: 1194 case KE_KEY:
1179 set_bit(EV_KEY, ehotk->inputdev->evbit); 1195 set_bit(EV_KEY, eeepc->inputdev->evbit);
1180 set_bit(key->keycode, ehotk->inputdev->keybit); 1196 set_bit(key->keycode, eeepc->inputdev->keybit);
1181 break; 1197 break;
1182 } 1198 }
1183 } 1199 }
1184 result = input_register_device(ehotk->inputdev); 1200 result = input_register_device(eeepc->inputdev);
1185 if (result) { 1201 if (result) {
1186 pr_info("Unable to register input device\n"); 1202 pr_info("Unable to register input device\n");
1187 input_free_device(ehotk->inputdev); 1203 input_free_device(eeepc->inputdev);
1188 return result; 1204 return result;
1189 } 1205 }
1190 return 0; 1206 return 0;
1191} 1207}
1192 1208
1193static int __devinit eeepc_hotk_add(struct acpi_device *device) 1209static void eeepc_input_exit(struct eeepc_laptop *eeepc)
1194{ 1210{
1195 struct device *dev; 1211 if (eeepc->inputdev) {
1212 input_unregister_device(eeepc->inputdev);
1213 kfree(eeepc->keymap);
1214 }
1215}
1216
1217/*
1218 * ACPI driver
1219 */
1220static void eeepc_acpi_notify(struct acpi_device *device, u32 event)
1221{
1222 struct eeepc_laptop *eeepc = acpi_driver_data(device);
1223 u16 count;
1224
1225 if (event > ACPI_MAX_SYS_NOTIFY)
1226 return;
1227 count = eeepc->event_count[event % 128]++;
1228 acpi_bus_generate_proc_event(device, event, count);
1229 acpi_bus_generate_netlink_event(device->pnp.device_class,
1230 dev_name(&device->dev), event,
1231 count);
1232
1233 /* Brightness events are special */
1234 if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) {
1235
1236 /* Ignore them completely if the acpi video driver is used */
1237 if (eeepc->backlight_device != NULL) {
1238 int old_brightness, new_brightness;
1239
1240 /* Update the backlight device. */
1241 old_brightness = eeepc_backlight_notify(eeepc);
1242
1243 /* Convert event to keypress (obsolescent hack) */
1244 new_brightness = event - NOTIFY_BRN_MIN;
1245
1246 if (new_brightness < old_brightness) {
1247 event = NOTIFY_BRN_MIN; /* brightness down */
1248 } else if (new_brightness > old_brightness) {
1249 event = NOTIFY_BRN_MAX; /* brightness up */
1250 } else {
1251 /*
1252 * no change in brightness - already at min/max,
1253 * event will be desired value (or else ignored)
1254 */
1255 }
1256 eeepc_input_notify(eeepc, event);
1257 }
1258 } else {
1259 /* Everything else is a bona-fide keypress event */
1260 eeepc_input_notify(eeepc, event);
1261 }
1262}
1263
1264static void cmsg_quirk(struct eeepc_laptop *eeepc, int cm, const char *name)
1265{
1266 int dummy;
1267
1268 /* Some BIOSes do not report cm although it is avaliable.
1269 Check if cm_getv[cm] works and, if yes, assume cm should be set. */
1270 if (!(eeepc->cm_supported & (1 << cm))
1271 && !read_acpi_int(eeepc->handle, cm_getv[cm], &dummy)) {
1272 pr_info("%s (%x) not reported by BIOS,"
1273 " enabling anyway\n", name, 1 << cm);
1274 eeepc->cm_supported |= 1 << cm;
1275 }
1276}
1277
1278static void cmsg_quirks(struct eeepc_laptop *eeepc)
1279{
1280 cmsg_quirk(eeepc, CM_ASL_LID, "LID");
1281 cmsg_quirk(eeepc, CM_ASL_TYPE, "TYPE");
1282 cmsg_quirk(eeepc, CM_ASL_PANELPOWER, "PANELPOWER");
1283 cmsg_quirk(eeepc, CM_ASL_TPD, "TPD");
1284}
1285
1286static int eeepc_acpi_init(struct eeepc_laptop *eeepc,
1287 struct acpi_device *device)
1288{
1289 unsigned int init_flags;
1196 int result; 1290 int result;
1197 1291
1198 if (!device) 1292 result = acpi_bus_get_status(device);
1199 return -EINVAL;
1200 pr_notice(EEEPC_HOTK_NAME "\n");
1201 ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL);
1202 if (!ehotk)
1203 return -ENOMEM;
1204 ehotk->init_flag = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH;
1205 ehotk->handle = device->handle;
1206 strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME);
1207 strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS);
1208 device->driver_data = ehotk;
1209 ehotk->device = device;
1210
1211 result = eeepc_hotk_check();
1212 if (result) 1293 if (result)
1213 goto fail_platform_driver; 1294 return result;
1214 eeepc_enable_camera(); 1295 if (!device->status.present) {
1296 pr_err("Hotkey device not present, aborting\n");
1297 return -ENODEV;
1298 }
1215 1299
1216 /* Register platform stuff */ 1300 init_flags = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH;
1217 result = platform_driver_register(&platform_driver); 1301 pr_notice("Hotkey init flags 0x%x\n", init_flags);
1218 if (result) 1302
1219 goto fail_platform_driver; 1303 if (write_acpi_int(eeepc->handle, "INIT", init_flags)) {
1220 platform_device = platform_device_alloc(EEEPC_HOTK_FILE, -1); 1304 pr_err("Hotkey initialization failed\n");
1221 if (!platform_device) { 1305 return -ENODEV;
1222 result = -ENOMEM;
1223 goto fail_platform_device1;
1224 } 1306 }
1225 result = platform_device_add(platform_device); 1307
1226 if (result) 1308 /* get control methods supported */
1227 goto fail_platform_device2; 1309 if (read_acpi_int(eeepc->handle, "CMSG", &eeepc->cm_supported)) {
1228 result = sysfs_create_group(&platform_device->dev.kobj, 1310 pr_err("Get control methods supported failed\n");
1229 &platform_attribute_group); 1311 return -ENODEV;
1312 }
1313 cmsg_quirks(eeepc);
1314 pr_info("Get control methods supported: 0x%x\n", eeepc->cm_supported);
1315
1316 return 0;
1317}
1318
1319static void __devinit eeepc_enable_camera(struct eeepc_laptop *eeepc)
1320{
1321 /*
1322 * If the following call to set_acpi() fails, it's because there's no
1323 * camera so we can ignore the error.
1324 */
1325 if (get_acpi(eeepc, CM_ASL_CAMERA) == 0)
1326 set_acpi(eeepc, CM_ASL_CAMERA, 1);
1327}
1328
1329static bool eeepc_device_present;
1330
1331static int __devinit eeepc_acpi_add(struct acpi_device *device)
1332{
1333 struct eeepc_laptop *eeepc;
1334 int result;
1335
1336 pr_notice(EEEPC_LAPTOP_NAME "\n");
1337 eeepc = kzalloc(sizeof(struct eeepc_laptop), GFP_KERNEL);
1338 if (!eeepc)
1339 return -ENOMEM;
1340 eeepc->handle = device->handle;
1341 strcpy(acpi_device_name(device), EEEPC_ACPI_DEVICE_NAME);
1342 strcpy(acpi_device_class(device), EEEPC_ACPI_CLASS);
1343 device->driver_data = eeepc;
1344
1345 result = eeepc_acpi_init(eeepc, device);
1230 if (result) 1346 if (result)
1231 goto fail_sysfs; 1347 goto fail_platform;
1348 eeepc_enable_camera(eeepc);
1232 1349
1233 dev = &platform_device->dev; 1350 /*
1351 * Register the platform device first. It is used as a parent for the
1352 * sub-devices below.
1353 *
1354 * Note that if there are multiple instances of this ACPI device it
1355 * will bail out, because the platform device is registered with a
1356 * fixed name. Of course it doesn't make sense to have more than one,
1357 * and machine-specific scripts find the fixed name convenient. But
1358 * It's also good for us to exclude multiple instances because both
1359 * our hwmon and our wlan rfkill subdevice use global ACPI objects
1360 * (the EC and the wlan PCI slot respectively).
1361 */
1362 result = eeepc_platform_init(eeepc);
1363 if (result)
1364 goto fail_platform;
1234 1365
1235 if (!acpi_video_backlight_support()) { 1366 if (!acpi_video_backlight_support()) {
1236 result = eeepc_backlight_init(dev); 1367 result = eeepc_backlight_init(eeepc);
1237 if (result) 1368 if (result)
1238 goto fail_backlight; 1369 goto fail_backlight;
1239 } else 1370 } else
1240 pr_info("Backlight controlled by ACPI video " 1371 pr_info("Backlight controlled by ACPI video driver\n");
1241 "driver\n");
1242 1372
1243 result = eeepc_input_init(dev); 1373 result = eeepc_input_init(eeepc);
1244 if (result) 1374 if (result)
1245 goto fail_input; 1375 goto fail_input;
1246 1376
1247 result = eeepc_hwmon_init(dev); 1377 result = eeepc_hwmon_init(eeepc);
1248 if (result) 1378 if (result)
1249 goto fail_hwmon; 1379 goto fail_hwmon;
1250 1380
1251 result = eeepc_rfkill_init(dev); 1381 result = eeepc_led_init(eeepc);
1382 if (result)
1383 goto fail_led;
1384
1385 result = eeepc_rfkill_init(eeepc);
1252 if (result) 1386 if (result)
1253 goto fail_rfkill; 1387 goto fail_rfkill;
1254 1388
1389 eeepc_device_present = true;
1255 return 0; 1390 return 0;
1256 1391
1257fail_rfkill: 1392fail_rfkill:
1258 eeepc_hwmon_exit(); 1393 eeepc_led_exit(eeepc);
1394fail_led:
1395 eeepc_hwmon_exit(eeepc);
1259fail_hwmon: 1396fail_hwmon:
1260 eeepc_input_exit(); 1397 eeepc_input_exit(eeepc);
1261fail_input: 1398fail_input:
1262 eeepc_backlight_exit(); 1399 eeepc_backlight_exit(eeepc);
1263fail_backlight: 1400fail_backlight:
1264 sysfs_remove_group(&platform_device->dev.kobj, 1401 eeepc_platform_exit(eeepc);
1265 &platform_attribute_group); 1402fail_platform:
1266fail_sysfs: 1403 kfree(eeepc);
1267 platform_device_del(platform_device);
1268fail_platform_device2:
1269 platform_device_put(platform_device);
1270fail_platform_device1:
1271 platform_driver_unregister(&platform_driver);
1272fail_platform_driver:
1273 kfree(ehotk);
1274 1404
1275 return result; 1405 return result;
1276} 1406}
1277 1407
1278static int eeepc_hotk_remove(struct acpi_device *device, int type) 1408static int eeepc_acpi_remove(struct acpi_device *device, int type)
1279{ 1409{
1280 if (!device || !acpi_driver_data(device)) 1410 struct eeepc_laptop *eeepc = acpi_driver_data(device);
1281 return -EINVAL;
1282 1411
1283 eeepc_backlight_exit(); 1412 eeepc_backlight_exit(eeepc);
1284 eeepc_rfkill_exit(); 1413 eeepc_rfkill_exit(eeepc);
1285 eeepc_input_exit(); 1414 eeepc_input_exit(eeepc);
1286 eeepc_hwmon_exit(); 1415 eeepc_hwmon_exit(eeepc);
1287 sysfs_remove_group(&platform_device->dev.kobj, 1416 eeepc_led_exit(eeepc);
1288 &platform_attribute_group); 1417 eeepc_platform_exit(eeepc);
1289 platform_device_unregister(platform_device);
1290 platform_driver_unregister(&platform_driver);
1291 1418
1292 kfree(ehotk); 1419 kfree(eeepc);
1293 return 0; 1420 return 0;
1294} 1421}
1295 1422
1423
1424static const struct acpi_device_id eeepc_device_ids[] = {
1425 {EEEPC_ACPI_HID, 0},
1426 {"", 0},
1427};
1428MODULE_DEVICE_TABLE(acpi, eeepc_device_ids);
1429
1430static struct acpi_driver eeepc_acpi_driver = {
1431 .name = EEEPC_LAPTOP_NAME,
1432 .class = EEEPC_ACPI_CLASS,
1433 .owner = THIS_MODULE,
1434 .ids = eeepc_device_ids,
1435 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
1436 .ops = {
1437 .add = eeepc_acpi_add,
1438 .remove = eeepc_acpi_remove,
1439 .notify = eeepc_acpi_notify,
1440 },
1441};
1442
1443
1296static int __init eeepc_laptop_init(void) 1444static int __init eeepc_laptop_init(void)
1297{ 1445{
1298 int result; 1446 int result;
1299 1447
1300 if (acpi_disabled) 1448 result = platform_driver_register(&platform_driver);
1301 return -ENODEV;
1302 result = acpi_bus_register_driver(&eeepc_hotk_driver);
1303 if (result < 0) 1449 if (result < 0)
1304 return result; 1450 return result;
1305 if (!ehotk) { 1451
1306 acpi_bus_unregister_driver(&eeepc_hotk_driver); 1452 result = acpi_bus_register_driver(&eeepc_acpi_driver);
1307 return -ENODEV; 1453 if (result < 0)
1454 goto fail_acpi_driver;
1455 if (!eeepc_device_present) {
1456 result = -ENODEV;
1457 goto fail_no_device;
1308 } 1458 }
1309 return 0; 1459 return 0;
1460
1461fail_no_device:
1462 acpi_bus_unregister_driver(&eeepc_acpi_driver);
1463fail_acpi_driver:
1464 platform_driver_unregister(&platform_driver);
1465 return result;
1310} 1466}
1311 1467
1312static void __exit eeepc_laptop_exit(void) 1468static void __exit eeepc_laptop_exit(void)
1313{ 1469{
1314 acpi_bus_unregister_driver(&eeepc_hotk_driver); 1470 acpi_bus_unregister_driver(&eeepc_acpi_driver);
1471 platform_driver_unregister(&platform_driver);
1315} 1472}
1316 1473
1317module_init(eeepc_laptop_init); 1474module_init(eeepc_laptop_init);
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
index f00a71c58e69..63c3e658a884 100644
--- a/drivers/platform/x86/hp-wmi.c
+++ b/drivers/platform/x86/hp-wmi.c
@@ -51,6 +51,12 @@ MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4");
51#define HPWMI_WIRELESS_QUERY 0x5 51#define HPWMI_WIRELESS_QUERY 0x5
52#define HPWMI_HOTKEY_QUERY 0xc 52#define HPWMI_HOTKEY_QUERY 0xc
53 53
54enum hp_wmi_radio {
55 HPWMI_WIFI = 0,
56 HPWMI_BLUETOOTH = 1,
57 HPWMI_WWAN = 2,
58};
59
54static int __init hp_wmi_bios_setup(struct platform_device *device); 60static int __init hp_wmi_bios_setup(struct platform_device *device);
55static int __exit hp_wmi_bios_remove(struct platform_device *device); 61static int __exit hp_wmi_bios_remove(struct platform_device *device);
56static int hp_wmi_resume_handler(struct device *device); 62static int hp_wmi_resume_handler(struct device *device);
@@ -175,8 +181,8 @@ static int hp_wmi_tablet_state(void)
175 181
176static int hp_wmi_set_block(void *data, bool blocked) 182static int hp_wmi_set_block(void *data, bool blocked)
177{ 183{
178 unsigned long b = (unsigned long) data; 184 enum hp_wmi_radio r = (enum hp_wmi_radio) data;
179 int query = BIT(b + 8) | ((!blocked) << b); 185 int query = BIT(r + 8) | ((!blocked) << r);
180 186
181 return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, query); 187 return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, query);
182} 188}
@@ -185,31 +191,23 @@ static const struct rfkill_ops hp_wmi_rfkill_ops = {
185 .set_block = hp_wmi_set_block, 191 .set_block = hp_wmi_set_block,
186}; 192};
187 193
188static bool hp_wmi_wifi_state(void) 194static bool hp_wmi_get_sw_state(enum hp_wmi_radio r)
189{
190 int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
191
192 if (wireless & 0x100)
193 return false;
194 else
195 return true;
196}
197
198static bool hp_wmi_bluetooth_state(void)
199{ 195{
200 int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); 196 int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
197 int mask = 0x200 << (r * 8);
201 198
202 if (wireless & 0x10000) 199 if (wireless & mask)
203 return false; 200 return false;
204 else 201 else
205 return true; 202 return true;
206} 203}
207 204
208static bool hp_wmi_wwan_state(void) 205static bool hp_wmi_get_hw_state(enum hp_wmi_radio r)
209{ 206{
210 int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); 207 int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0);
208 int mask = 0x800 << (r * 8);
211 209
212 if (wireless & 0x1000000) 210 if (wireless & mask)
213 return false; 211 return false;
214 else 212 else
215 return true; 213 return true;
@@ -334,49 +332,55 @@ static void hp_wmi_notify(u32 value, void *context)
334 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 332 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
335 static struct key_entry *key; 333 static struct key_entry *key;
336 union acpi_object *obj; 334 union acpi_object *obj;
335 int eventcode;
337 336
338 wmi_get_event_data(value, &response); 337 wmi_get_event_data(value, &response);
339 338
340 obj = (union acpi_object *)response.pointer; 339 obj = (union acpi_object *)response.pointer;
341 340
342 if (obj && obj->type == ACPI_TYPE_BUFFER && obj->buffer.length == 8) { 341 if (!obj || obj->type != ACPI_TYPE_BUFFER || obj->buffer.length != 8) {
343 int eventcode = *((u8 *) obj->buffer.pointer); 342 printk(KERN_INFO "HP WMI: Unknown response received\n");
344 if (eventcode == 0x4) 343 return;
345 eventcode = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0, 344 }
346 0); 345
347 key = hp_wmi_get_entry_by_scancode(eventcode); 346 eventcode = *((u8 *) obj->buffer.pointer);
348 if (key) { 347 if (eventcode == 0x4)
349 switch (key->type) { 348 eventcode = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0,
350 case KE_KEY: 349 0);
351 input_report_key(hp_wmi_input_dev, 350 key = hp_wmi_get_entry_by_scancode(eventcode);
352 key->keycode, 1); 351 if (key) {
353 input_sync(hp_wmi_input_dev); 352 switch (key->type) {
354 input_report_key(hp_wmi_input_dev, 353 case KE_KEY:
355 key->keycode, 0); 354 input_report_key(hp_wmi_input_dev,
356 input_sync(hp_wmi_input_dev); 355 key->keycode, 1);
357 break; 356 input_sync(hp_wmi_input_dev);
358 } 357 input_report_key(hp_wmi_input_dev,
359 } else if (eventcode == 0x1) { 358 key->keycode, 0);
360 input_report_switch(hp_wmi_input_dev, SW_DOCK,
361 hp_wmi_dock_state());
362 input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
363 hp_wmi_tablet_state());
364 input_sync(hp_wmi_input_dev); 359 input_sync(hp_wmi_input_dev);
365 } else if (eventcode == 0x5) { 360 break;
366 if (wifi_rfkill) 361 }
367 rfkill_set_sw_state(wifi_rfkill, 362 } else if (eventcode == 0x1) {
368 hp_wmi_wifi_state()); 363 input_report_switch(hp_wmi_input_dev, SW_DOCK,
369 if (bluetooth_rfkill) 364 hp_wmi_dock_state());
370 rfkill_set_sw_state(bluetooth_rfkill, 365 input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE,
371 hp_wmi_bluetooth_state()); 366 hp_wmi_tablet_state());
372 if (wwan_rfkill) 367 input_sync(hp_wmi_input_dev);
373 rfkill_set_sw_state(wwan_rfkill, 368 } else if (eventcode == 0x5) {
374 hp_wmi_wwan_state()); 369 if (wifi_rfkill)
375 } else 370 rfkill_set_states(wifi_rfkill,
376 printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n", 371 hp_wmi_get_sw_state(HPWMI_WIFI),
377 eventcode); 372 hp_wmi_get_hw_state(HPWMI_WIFI));
373 if (bluetooth_rfkill)
374 rfkill_set_states(bluetooth_rfkill,
375 hp_wmi_get_sw_state(HPWMI_BLUETOOTH),
376 hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
377 if (wwan_rfkill)
378 rfkill_set_states(wwan_rfkill,
379 hp_wmi_get_sw_state(HPWMI_WWAN),
380 hp_wmi_get_hw_state(HPWMI_WWAN));
378 } else 381 } else
379 printk(KERN_INFO "HP WMI: Unknown response received\n"); 382 printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n",
383 eventcode);
380} 384}
381 385
382static int __init hp_wmi_input_setup(void) 386static int __init hp_wmi_input_setup(void)
@@ -455,7 +459,11 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
455 wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev, 459 wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev,
456 RFKILL_TYPE_WLAN, 460 RFKILL_TYPE_WLAN,
457 &hp_wmi_rfkill_ops, 461 &hp_wmi_rfkill_ops,
458 (void *) 0); 462 (void *) HPWMI_WIFI);
463 rfkill_init_sw_state(wifi_rfkill,
464 hp_wmi_get_sw_state(HPWMI_WIFI));
465 rfkill_set_hw_state(wifi_rfkill,
466 hp_wmi_get_hw_state(HPWMI_WIFI));
459 err = rfkill_register(wifi_rfkill); 467 err = rfkill_register(wifi_rfkill);
460 if (err) 468 if (err)
461 goto register_wifi_error; 469 goto register_wifi_error;
@@ -465,7 +473,11 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
465 bluetooth_rfkill = rfkill_alloc("hp-bluetooth", &device->dev, 473 bluetooth_rfkill = rfkill_alloc("hp-bluetooth", &device->dev,
466 RFKILL_TYPE_BLUETOOTH, 474 RFKILL_TYPE_BLUETOOTH,
467 &hp_wmi_rfkill_ops, 475 &hp_wmi_rfkill_ops,
468 (void *) 1); 476 (void *) HPWMI_BLUETOOTH);
477 rfkill_init_sw_state(bluetooth_rfkill,
478 hp_wmi_get_sw_state(HPWMI_BLUETOOTH));
479 rfkill_set_hw_state(bluetooth_rfkill,
480 hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
469 err = rfkill_register(bluetooth_rfkill); 481 err = rfkill_register(bluetooth_rfkill);
470 if (err) 482 if (err)
471 goto register_bluetooth_error; 483 goto register_bluetooth_error;
@@ -475,7 +487,11 @@ static int __init hp_wmi_bios_setup(struct platform_device *device)
475 wwan_rfkill = rfkill_alloc("hp-wwan", &device->dev, 487 wwan_rfkill = rfkill_alloc("hp-wwan", &device->dev,
476 RFKILL_TYPE_WWAN, 488 RFKILL_TYPE_WWAN,
477 &hp_wmi_rfkill_ops, 489 &hp_wmi_rfkill_ops,
478 (void *) 2); 490 (void *) HPWMI_WWAN);
491 rfkill_init_sw_state(wwan_rfkill,
492 hp_wmi_get_sw_state(HPWMI_WWAN));
493 rfkill_set_hw_state(wwan_rfkill,
494 hp_wmi_get_hw_state(HPWMI_WWAN));
479 err = rfkill_register(wwan_rfkill); 495 err = rfkill_register(wwan_rfkill);
480 if (err) 496 if (err)
481 goto register_wwan_err; 497 goto register_wwan_err;
@@ -533,6 +549,19 @@ static int hp_wmi_resume_handler(struct device *device)
533 input_sync(hp_wmi_input_dev); 549 input_sync(hp_wmi_input_dev);
534 } 550 }
535 551
552 if (wifi_rfkill)
553 rfkill_set_states(wifi_rfkill,
554 hp_wmi_get_sw_state(HPWMI_WIFI),
555 hp_wmi_get_hw_state(HPWMI_WIFI));
556 if (bluetooth_rfkill)
557 rfkill_set_states(bluetooth_rfkill,
558 hp_wmi_get_sw_state(HPWMI_BLUETOOTH),
559 hp_wmi_get_hw_state(HPWMI_BLUETOOTH));
560 if (wwan_rfkill)
561 rfkill_set_states(wwan_rfkill,
562 hp_wmi_get_sw_state(HPWMI_WWAN),
563 hp_wmi_get_hw_state(HPWMI_WWAN));
564
536 return 0; 565 return 0;
537} 566}
538 567
diff --git a/drivers/platform/x86/msi-wmi.c b/drivers/platform/x86/msi-wmi.c
new file mode 100644
index 000000000000..0c8fe145c4af
--- /dev/null
+++ b/drivers/platform/x86/msi-wmi.c
@@ -0,0 +1,293 @@
1/*
2 * MSI WMI hotkeys
3 *
4 * Copyright (C) 2009 Novell <trenn@suse.de>
5 *
6 * Most stuff taken over from hp-wmi
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23
24#include <linux/kernel.h>
25#include <linux/input.h>
26#include <linux/input/sparse-keymap.h>
27#include <linux/acpi.h>
28#include <linux/backlight.h>
29
30MODULE_AUTHOR("Thomas Renninger <trenn@suse.de>");
31MODULE_DESCRIPTION("MSI laptop WMI hotkeys driver");
32MODULE_LICENSE("GPL");
33
34MODULE_ALIAS("wmi:551A1F84-FBDD-4125-91DB-3EA8F44F1D45");
35MODULE_ALIAS("wmi:B6F3EEF2-3D2F-49DC-9DE3-85BCE18C62F2");
36
37/* Temporary workaround until the WMI sysfs interface goes in
38 { "svn", DMI_SYS_VENDOR },
39 { "pn", DMI_PRODUCT_NAME },
40 { "pvr", DMI_PRODUCT_VERSION },
41 { "rvn", DMI_BOARD_VENDOR },
42 { "rn", DMI_BOARD_NAME },
43*/
44
45MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-6638:*");
46
47#define DRV_NAME "msi-wmi"
48#define DRV_PFX DRV_NAME ": "
49
50#define MSIWMI_BIOS_GUID "551A1F84-FBDD-4125-91DB-3EA8F44F1D45"
51#define MSIWMI_EVENT_GUID "B6F3EEF2-3D2F-49DC-9DE3-85BCE18C62F2"
52
53#define dprintk(msg...) pr_debug(DRV_PFX msg)
54
55#define KEYCODE_BASE 0xD0
56#define MSI_WMI_BRIGHTNESSUP KEYCODE_BASE
57#define MSI_WMI_BRIGHTNESSDOWN (KEYCODE_BASE + 1)
58#define MSI_WMI_VOLUMEUP (KEYCODE_BASE + 2)
59#define MSI_WMI_VOLUMEDOWN (KEYCODE_BASE + 3)
60static struct key_entry msi_wmi_keymap[] = {
61 { KE_KEY, MSI_WMI_BRIGHTNESSUP, {KEY_BRIGHTNESSUP} },
62 { KE_KEY, MSI_WMI_BRIGHTNESSDOWN, {KEY_BRIGHTNESSDOWN} },
63 { KE_KEY, MSI_WMI_VOLUMEUP, {KEY_VOLUMEUP} },
64 { KE_KEY, MSI_WMI_VOLUMEDOWN, {KEY_VOLUMEDOWN} },
65 { KE_END, 0}
66};
67static ktime_t last_pressed[ARRAY_SIZE(msi_wmi_keymap) - 1];
68
69struct backlight_device *backlight;
70
71static int backlight_map[] = { 0x00, 0x33, 0x66, 0x99, 0xCC, 0xFF };
72
73static struct input_dev *msi_wmi_input_dev;
74
75static int msi_wmi_query_block(int instance, int *ret)
76{
77 acpi_status status;
78 union acpi_object *obj;
79
80 struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
81
82 status = wmi_query_block(MSIWMI_BIOS_GUID, instance, &output);
83
84 obj = output.pointer;
85
86 if (!obj || obj->type != ACPI_TYPE_INTEGER) {
87 if (obj) {
88 printk(KERN_ERR DRV_PFX "query block returned object "
89 "type: %d - buffer length:%d\n", obj->type,
90 obj->type == ACPI_TYPE_BUFFER ?
91 obj->buffer.length : 0);
92 }
93 kfree(obj);
94 return -EINVAL;
95 }
96 *ret = obj->integer.value;
97 kfree(obj);
98 return 0;
99}
100
101static int msi_wmi_set_block(int instance, int value)
102{
103 acpi_status status;
104
105 struct acpi_buffer input = { sizeof(int), &value };
106
107 dprintk("Going to set block of instance: %d - value: %d\n",
108 instance, value);
109
110 status = wmi_set_block(MSIWMI_BIOS_GUID, instance, &input);
111
112 return ACPI_SUCCESS(status) ? 0 : 1;
113}
114
115static int bl_get(struct backlight_device *bd)
116{
117 int level, err, ret;
118
119 /* Instance 1 is "get backlight", cmp with DSDT */
120 err = msi_wmi_query_block(1, &ret);
121 if (err) {
122 printk(KERN_ERR DRV_PFX "Could not query backlight: %d\n", err);
123 return -EINVAL;
124 }
125 dprintk("Get: Query block returned: %d\n", ret);
126 for (level = 0; level < ARRAY_SIZE(backlight_map); level++) {
127 if (backlight_map[level] == ret) {
128 dprintk("Current backlight level: 0x%X - index: %d\n",
129 backlight_map[level], level);
130 break;
131 }
132 }
133 if (level == ARRAY_SIZE(backlight_map)) {
134 printk(KERN_ERR DRV_PFX "get: Invalid brightness value: 0x%X\n",
135 ret);
136 return -EINVAL;
137 }
138 return level;
139}
140
141static int bl_set_status(struct backlight_device *bd)
142{
143 int bright = bd->props.brightness;
144 if (bright >= ARRAY_SIZE(backlight_map) || bright < 0)
145 return -EINVAL;
146
147 /* Instance 0 is "set backlight" */
148 return msi_wmi_set_block(0, backlight_map[bright]);
149}
150
151static struct backlight_ops msi_backlight_ops = {
152 .get_brightness = bl_get,
153 .update_status = bl_set_status,
154};
155
156static void msi_wmi_notify(u32 value, void *context)
157{
158 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
159 static struct key_entry *key;
160 union acpi_object *obj;
161 ktime_t cur;
162
163 wmi_get_event_data(value, &response);
164
165 obj = (union acpi_object *)response.pointer;
166
167 if (obj && obj->type == ACPI_TYPE_INTEGER) {
168 int eventcode = obj->integer.value;
169 dprintk("Eventcode: 0x%x\n", eventcode);
170 key = sparse_keymap_entry_from_scancode(msi_wmi_input_dev,
171 eventcode);
172 if (key) {
173 ktime_t diff;
174 cur = ktime_get_real();
175 diff = ktime_sub(cur, last_pressed[key->code -
176 KEYCODE_BASE]);
177 /* Ignore event if the same event happened in a 50 ms
178 timeframe -> Key press may result in 10-20 GPEs */
179 if (ktime_to_us(diff) < 1000 * 50) {
180 dprintk("Suppressed key event 0x%X - "
181 "Last press was %lld us ago\n",
182 key->code, ktime_to_us(diff));
183 return;
184 }
185 last_pressed[key->code - KEYCODE_BASE] = cur;
186
187 if (key->type == KE_KEY &&
188 /* Brightness is served via acpi video driver */
189 (!acpi_video_backlight_support() ||
190 (key->code != MSI_WMI_BRIGHTNESSUP &&
191 key->code != MSI_WMI_BRIGHTNESSDOWN))) {
192 dprintk("Send key: 0x%X - "
193 "Input layer keycode: %d\n", key->code,
194 key->keycode);
195 sparse_keymap_report_entry(msi_wmi_input_dev,
196 key, 1, true);
197 }
198 } else
199 printk(KERN_INFO "Unknown key pressed - %x\n",
200 eventcode);
201 } else
202 printk(KERN_INFO DRV_PFX "Unknown event received\n");
203 kfree(response.pointer);
204}
205
206static int __init msi_wmi_input_setup(void)
207{
208 int err;
209
210 msi_wmi_input_dev = input_allocate_device();
211 if (!msi_wmi_input_dev)
212 return -ENOMEM;
213
214 msi_wmi_input_dev->name = "MSI WMI hotkeys";
215 msi_wmi_input_dev->phys = "wmi/input0";
216 msi_wmi_input_dev->id.bustype = BUS_HOST;
217
218 err = sparse_keymap_setup(msi_wmi_input_dev, msi_wmi_keymap, NULL);
219 if (err)
220 goto err_free_dev;
221
222 err = input_register_device(msi_wmi_input_dev);
223
224 if (err)
225 goto err_free_keymap;
226
227 memset(last_pressed, 0, sizeof(last_pressed));
228
229 return 0;
230
231err_free_keymap:
232 sparse_keymap_free(msi_wmi_input_dev);
233err_free_dev:
234 input_free_device(msi_wmi_input_dev);
235 return err;
236}
237
238static int __init msi_wmi_init(void)
239{
240 int err;
241
242 if (!wmi_has_guid(MSIWMI_EVENT_GUID)) {
243 printk(KERN_ERR
244 "This machine doesn't have MSI-hotkeys through WMI\n");
245 return -ENODEV;
246 }
247 err = wmi_install_notify_handler(MSIWMI_EVENT_GUID,
248 msi_wmi_notify, NULL);
249 if (err)
250 return -EINVAL;
251
252 err = msi_wmi_input_setup();
253 if (err)
254 goto err_uninstall_notifier;
255
256 if (!acpi_video_backlight_support()) {
257 backlight = backlight_device_register(DRV_NAME,
258 NULL, NULL, &msi_backlight_ops);
259 if (IS_ERR(backlight))
260 goto err_free_input;
261
262 backlight->props.max_brightness = ARRAY_SIZE(backlight_map) - 1;
263 err = bl_get(NULL);
264 if (err < 0)
265 goto err_free_backlight;
266
267 backlight->props.brightness = err;
268 }
269 dprintk("Event handler installed\n");
270
271 return 0;
272
273err_free_backlight:
274 backlight_device_unregister(backlight);
275err_free_input:
276 input_unregister_device(msi_wmi_input_dev);
277err_uninstall_notifier:
278 wmi_remove_notify_handler(MSIWMI_EVENT_GUID);
279 return err;
280}
281
282static void __exit msi_wmi_exit(void)
283{
284 if (wmi_has_guid(MSIWMI_EVENT_GUID)) {
285 wmi_remove_notify_handler(MSIWMI_EVENT_GUID);
286 sparse_keymap_free(msi_wmi_input_dev);
287 input_unregister_device(msi_wmi_input_dev);
288 backlight_device_unregister(backlight);
289 }
290}
291
292module_init(msi_wmi_init);
293module_exit(msi_wmi_exit);
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index cf61d6a8ef6f..448c8aeb166b 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -21,8 +21,8 @@
21 * 02110-1301, USA. 21 * 02110-1301, USA.
22 */ 22 */
23 23
24#define TPACPI_VERSION "0.23" 24#define TPACPI_VERSION "0.24"
25#define TPACPI_SYSFS_VERSION 0x020500 25#define TPACPI_SYSFS_VERSION 0x020700
26 26
27/* 27/*
28 * Changelog: 28 * Changelog:
@@ -61,6 +61,7 @@
61 61
62#include <linux/nvram.h> 62#include <linux/nvram.h>
63#include <linux/proc_fs.h> 63#include <linux/proc_fs.h>
64#include <linux/seq_file.h>
64#include <linux/sysfs.h> 65#include <linux/sysfs.h>
65#include <linux/backlight.h> 66#include <linux/backlight.h>
66#include <linux/fb.h> 67#include <linux/fb.h>
@@ -76,6 +77,10 @@
76#include <linux/jiffies.h> 77#include <linux/jiffies.h>
77#include <linux/workqueue.h> 78#include <linux/workqueue.h>
78 79
80#include <sound/core.h>
81#include <sound/control.h>
82#include <sound/initval.h>
83
79#include <acpi/acpi_drivers.h> 84#include <acpi/acpi_drivers.h>
80 85
81#include <linux/pci_ids.h> 86#include <linux/pci_ids.h>
@@ -231,6 +236,7 @@ enum tpacpi_hkey_event_t {
231#define TPACPI_DBG_HKEY 0x0008 236#define TPACPI_DBG_HKEY 0x0008
232#define TPACPI_DBG_FAN 0x0010 237#define TPACPI_DBG_FAN 0x0010
233#define TPACPI_DBG_BRGHT 0x0020 238#define TPACPI_DBG_BRGHT 0x0020
239#define TPACPI_DBG_MIXER 0x0040
234 240
235#define onoff(status, bit) ((status) & (1 << (bit)) ? "on" : "off") 241#define onoff(status, bit) ((status) & (1 << (bit)) ? "on" : "off")
236#define enabled(status, bit) ((status) & (1 << (bit)) ? "enabled" : "disabled") 242#define enabled(status, bit) ((status) & (1 << (bit)) ? "enabled" : "disabled")
@@ -256,7 +262,7 @@ struct tp_acpi_drv_struct {
256struct ibm_struct { 262struct ibm_struct {
257 char *name; 263 char *name;
258 264
259 int (*read) (char *); 265 int (*read) (struct seq_file *);
260 int (*write) (char *); 266 int (*write) (char *);
261 void (*exit) (void); 267 void (*exit) (void);
262 void (*resume) (void); 268 void (*resume) (void);
@@ -298,6 +304,7 @@ static struct {
298 u32 fan_ctrl_status_undef:1; 304 u32 fan_ctrl_status_undef:1;
299 u32 second_fan:1; 305 u32 second_fan:1;
300 u32 beep_needs_two_args:1; 306 u32 beep_needs_two_args:1;
307 u32 mixer_no_level_control:1;
301 u32 input_device_registered:1; 308 u32 input_device_registered:1;
302 u32 platform_drv_registered:1; 309 u32 platform_drv_registered:1;
303 u32 platform_drv_attrs_registered:1; 310 u32 platform_drv_attrs_registered:1;
@@ -309,6 +316,7 @@ static struct {
309 316
310static struct { 317static struct {
311 u16 hotkey_mask_ff:1; 318 u16 hotkey_mask_ff:1;
319 u16 volume_ctrl_forbidden:1;
312} tp_warned; 320} tp_warned;
313 321
314struct thinkpad_id_data { 322struct thinkpad_id_data {
@@ -425,6 +433,12 @@ static void tpacpi_log_usertask(const char * const what)
425 .ec = TPACPI_MATCH_ANY, \ 433 .ec = TPACPI_MATCH_ANY, \
426 .quirks = (__quirk) } 434 .quirks = (__quirk) }
427 435
436#define TPACPI_QEC_LNV(__id1, __id2, __quirk) \
437 { .vendor = PCI_VENDOR_ID_LENOVO, \
438 .bios = TPACPI_MATCH_ANY, \
439 .ec = TPID(__id1, __id2), \
440 .quirks = (__quirk) }
441
428struct tpacpi_quirk { 442struct tpacpi_quirk {
429 unsigned int vendor; 443 unsigned int vendor;
430 u16 bios; 444 u16 bios;
@@ -776,36 +790,25 @@ static int __init register_tpacpi_subdriver(struct ibm_struct *ibm)
776 **************************************************************************** 790 ****************************************************************************
777 ****************************************************************************/ 791 ****************************************************************************/
778 792
779static int dispatch_procfs_read(char *page, char **start, off_t off, 793static int dispatch_proc_show(struct seq_file *m, void *v)
780 int count, int *eof, void *data)
781{ 794{
782 struct ibm_struct *ibm = data; 795 struct ibm_struct *ibm = m->private;
783 int len;
784 796
785 if (!ibm || !ibm->read) 797 if (!ibm || !ibm->read)
786 return -EINVAL; 798 return -EINVAL;
799 return ibm->read(m);
800}
787 801
788 len = ibm->read(page); 802static int dispatch_proc_open(struct inode *inode, struct file *file)
789 if (len < 0) 803{
790 return len; 804 return single_open(file, dispatch_proc_show, PDE(inode)->data);
791
792 if (len <= off + count)
793 *eof = 1;
794 *start = page + off;
795 len -= off;
796 if (len > count)
797 len = count;
798 if (len < 0)
799 len = 0;
800
801 return len;
802} 805}
803 806
804static int dispatch_procfs_write(struct file *file, 807static ssize_t dispatch_proc_write(struct file *file,
805 const char __user *userbuf, 808 const char __user *userbuf,
806 unsigned long count, void *data) 809 size_t count, loff_t *pos)
807{ 810{
808 struct ibm_struct *ibm = data; 811 struct ibm_struct *ibm = PDE(file->f_path.dentry->d_inode)->data;
809 char *kernbuf; 812 char *kernbuf;
810 int ret; 813 int ret;
811 814
@@ -834,6 +837,15 @@ static int dispatch_procfs_write(struct file *file,
834 return ret; 837 return ret;
835} 838}
836 839
840static const struct file_operations dispatch_proc_fops = {
841 .owner = THIS_MODULE,
842 .open = dispatch_proc_open,
843 .read = seq_read,
844 .llseek = seq_lseek,
845 .release = single_release,
846 .write = dispatch_proc_write,
847};
848
837static char *next_cmd(char **cmds) 849static char *next_cmd(char **cmds)
838{ 850{
839 char *start = *cmds; 851 char *start = *cmds;
@@ -1261,6 +1273,7 @@ static int __init tpacpi_new_rfkill(const enum tpacpi_rfk_id id,
1261 struct tpacpi_rfk *atp_rfk; 1273 struct tpacpi_rfk *atp_rfk;
1262 int res; 1274 int res;
1263 bool sw_state = false; 1275 bool sw_state = false;
1276 bool hw_state;
1264 int sw_status; 1277 int sw_status;
1265 1278
1266 BUG_ON(id >= TPACPI_RFK_SW_MAX || tpacpi_rfkill_switches[id]); 1279 BUG_ON(id >= TPACPI_RFK_SW_MAX || tpacpi_rfkill_switches[id]);
@@ -1295,7 +1308,8 @@ static int __init tpacpi_new_rfkill(const enum tpacpi_rfk_id id,
1295 rfkill_init_sw_state(atp_rfk->rfkill, sw_state); 1308 rfkill_init_sw_state(atp_rfk->rfkill, sw_state);
1296 } 1309 }
1297 } 1310 }
1298 rfkill_set_hw_state(atp_rfk->rfkill, tpacpi_rfk_check_hwblock_state()); 1311 hw_state = tpacpi_rfk_check_hwblock_state();
1312 rfkill_set_hw_state(atp_rfk->rfkill, hw_state);
1299 1313
1300 res = rfkill_register(atp_rfk->rfkill); 1314 res = rfkill_register(atp_rfk->rfkill);
1301 if (res < 0) { 1315 if (res < 0) {
@@ -1308,6 +1322,9 @@ static int __init tpacpi_new_rfkill(const enum tpacpi_rfk_id id,
1308 } 1322 }
1309 1323
1310 tpacpi_rfkill_switches[id] = atp_rfk; 1324 tpacpi_rfkill_switches[id] = atp_rfk;
1325
1326 printk(TPACPI_INFO "rfkill switch %s: radio is %sblocked\n",
1327 name, (sw_state || hw_state) ? "" : "un");
1311 return 0; 1328 return 0;
1312} 1329}
1313 1330
@@ -1380,12 +1397,10 @@ static ssize_t tpacpi_rfk_sysfs_enable_store(const enum tpacpi_rfk_id id,
1380} 1397}
1381 1398
1382/* procfs -------------------------------------------------------------- */ 1399/* procfs -------------------------------------------------------------- */
1383static int tpacpi_rfk_procfs_read(const enum tpacpi_rfk_id id, char *p) 1400static int tpacpi_rfk_procfs_read(const enum tpacpi_rfk_id id, struct seq_file *m)
1384{ 1401{
1385 int len = 0;
1386
1387 if (id >= TPACPI_RFK_SW_MAX) 1402 if (id >= TPACPI_RFK_SW_MAX)
1388 len += sprintf(p + len, "status:\t\tnot supported\n"); 1403 seq_printf(m, "status:\t\tnot supported\n");
1389 else { 1404 else {
1390 int status; 1405 int status;
1391 1406
@@ -1399,13 +1414,13 @@ static int tpacpi_rfk_procfs_read(const enum tpacpi_rfk_id id, char *p)
1399 return status; 1414 return status;
1400 } 1415 }
1401 1416
1402 len += sprintf(p + len, "status:\t\t%s\n", 1417 seq_printf(m, "status:\t\t%s\n",
1403 (status == TPACPI_RFK_RADIO_ON) ? 1418 (status == TPACPI_RFK_RADIO_ON) ?
1404 "enabled" : "disabled"); 1419 "enabled" : "disabled");
1405 len += sprintf(p + len, "commands:\tenable, disable\n"); 1420 seq_printf(m, "commands:\tenable, disable\n");
1406 } 1421 }
1407 1422
1408 return len; 1423 return 0;
1409} 1424}
1410 1425
1411static int tpacpi_rfk_procfs_write(const enum tpacpi_rfk_id id, char *buf) 1426static int tpacpi_rfk_procfs_write(const enum tpacpi_rfk_id id, char *buf)
@@ -1776,7 +1791,7 @@ static const struct tpacpi_quirk tpacpi_bios_version_qtable[] __initconst = {
1776 1791
1777 TPV_QL1('7', '9', 'E', '3', '5', '0'), /* T60/p */ 1792 TPV_QL1('7', '9', 'E', '3', '5', '0'), /* T60/p */
1778 TPV_QL1('7', 'C', 'D', '2', '2', '2'), /* R60, R60i */ 1793 TPV_QL1('7', 'C', 'D', '2', '2', '2'), /* R60, R60i */
1779 TPV_QL0('7', 'E', 'D', '0'), /* R60e, R60i */ 1794 TPV_QL1('7', 'E', 'D', '0', '1', '5'), /* R60e, R60i */
1780 1795
1781 /* BIOS FW BIOS VERS EC FW EC VERS */ 1796 /* BIOS FW BIOS VERS EC FW EC VERS */
1782 TPV_QI2('1', 'W', '9', '0', '1', 'V', '2', '8'), /* R50e (1) */ 1797 TPV_QI2('1', 'W', '9', '0', '1', 'V', '2', '8'), /* R50e (1) */
@@ -1792,8 +1807,8 @@ static const struct tpacpi_quirk tpacpi_bios_version_qtable[] __initconst = {
1792 TPV_QI1('7', '4', '6', '4', '2', '7'), /* X41 (0) */ 1807 TPV_QI1('7', '4', '6', '4', '2', '7'), /* X41 (0) */
1793 TPV_QI1('7', '5', '6', '0', '2', '0'), /* X41t (0) */ 1808 TPV_QI1('7', '5', '6', '0', '2', '0'), /* X41t (0) */
1794 1809
1795 TPV_QL0('7', 'B', 'D', '7'), /* X60/s */ 1810 TPV_QL1('7', 'B', 'D', '7', '4', '0'), /* X60/s */
1796 TPV_QL0('7', 'J', '3', '0'), /* X60t */ 1811 TPV_QL1('7', 'J', '3', '0', '1', '3'), /* X60t */
1797 1812
1798 /* (0) - older versions lack DMI EC fw string and functionality */ 1813 /* (0) - older versions lack DMI EC fw string and functionality */
1799 /* (1) - older versions known to lack functionality */ 1814 /* (1) - older versions known to lack functionality */
@@ -1883,14 +1898,11 @@ static int __init thinkpad_acpi_driver_init(struct ibm_init_struct *iibm)
1883 return 0; 1898 return 0;
1884} 1899}
1885 1900
1886static int thinkpad_acpi_driver_read(char *p) 1901static int thinkpad_acpi_driver_read(struct seq_file *m)
1887{ 1902{
1888 int len = 0; 1903 seq_printf(m, "driver:\t\t%s\n", TPACPI_DESC);
1889 1904 seq_printf(m, "version:\t%s\n", TPACPI_VERSION);
1890 len += sprintf(p + len, "driver:\t\t%s\n", TPACPI_DESC); 1905 return 0;
1891 len += sprintf(p + len, "version:\t%s\n", TPACPI_VERSION);
1892
1893 return len;
1894} 1906}
1895 1907
1896static struct ibm_struct thinkpad_acpi_driver_data = { 1908static struct ibm_struct thinkpad_acpi_driver_data = {
@@ -2186,7 +2198,8 @@ static int hotkey_mask_set(u32 mask)
2186 fwmask, hotkey_acpi_mask); 2198 fwmask, hotkey_acpi_mask);
2187 } 2199 }
2188 2200
2189 hotkey_mask_warn_incomplete_mask(); 2201 if (tpacpi_lifecycle != TPACPI_LIFE_EXITING)
2202 hotkey_mask_warn_incomplete_mask();
2190 2203
2191 return rc; 2204 return rc;
2192} 2205}
@@ -3182,6 +3195,8 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3182 int res, i; 3195 int res, i;
3183 int status; 3196 int status;
3184 int hkeyv; 3197 int hkeyv;
3198 bool radiosw_state = false;
3199 bool tabletsw_state = false;
3185 3200
3186 unsigned long quirks; 3201 unsigned long quirks;
3187 3202
@@ -3287,6 +3302,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3287#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES 3302#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
3288 if (dbg_wlswemul) { 3303 if (dbg_wlswemul) {
3289 tp_features.hotkey_wlsw = 1; 3304 tp_features.hotkey_wlsw = 1;
3305 radiosw_state = !!tpacpi_wlsw_emulstate;
3290 printk(TPACPI_INFO 3306 printk(TPACPI_INFO
3291 "radio switch emulation enabled\n"); 3307 "radio switch emulation enabled\n");
3292 } else 3308 } else
@@ -3294,6 +3310,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3294 /* Not all thinkpads have a hardware radio switch */ 3310 /* Not all thinkpads have a hardware radio switch */
3295 if (acpi_evalf(hkey_handle, &status, "WLSW", "qd")) { 3311 if (acpi_evalf(hkey_handle, &status, "WLSW", "qd")) {
3296 tp_features.hotkey_wlsw = 1; 3312 tp_features.hotkey_wlsw = 1;
3313 radiosw_state = !!status;
3297 printk(TPACPI_INFO 3314 printk(TPACPI_INFO
3298 "radio switch found; radios are %s\n", 3315 "radio switch found; radios are %s\n",
3299 enabled(status, 0)); 3316 enabled(status, 0));
@@ -3305,11 +3322,11 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3305 /* For X41t, X60t, X61t Tablets... */ 3322 /* For X41t, X60t, X61t Tablets... */
3306 if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) { 3323 if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) {
3307 tp_features.hotkey_tablet = 1; 3324 tp_features.hotkey_tablet = 1;
3325 tabletsw_state = !!(status & TP_HOTKEY_TABLET_MASK);
3308 printk(TPACPI_INFO 3326 printk(TPACPI_INFO
3309 "possible tablet mode switch found; " 3327 "possible tablet mode switch found; "
3310 "ThinkPad in %s mode\n", 3328 "ThinkPad in %s mode\n",
3311 (status & TP_HOTKEY_TABLET_MASK)? 3329 (tabletsw_state) ? "tablet" : "laptop");
3312 "tablet" : "laptop");
3313 res = add_to_attr_set(hotkey_dev_attributes, 3330 res = add_to_attr_set(hotkey_dev_attributes,
3314 &dev_attr_hotkey_tablet_mode.attr); 3331 &dev_attr_hotkey_tablet_mode.attr);
3315 } 3332 }
@@ -3344,16 +3361,14 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3344 TPACPI_HOTKEY_MAP_SIZE); 3361 TPACPI_HOTKEY_MAP_SIZE);
3345 } 3362 }
3346 3363
3347 set_bit(EV_KEY, tpacpi_inputdev->evbit); 3364 input_set_capability(tpacpi_inputdev, EV_MSC, MSC_SCAN);
3348 set_bit(EV_MSC, tpacpi_inputdev->evbit);
3349 set_bit(MSC_SCAN, tpacpi_inputdev->mscbit);
3350 tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE; 3365 tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE;
3351 tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN; 3366 tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN;
3352 tpacpi_inputdev->keycode = hotkey_keycode_map; 3367 tpacpi_inputdev->keycode = hotkey_keycode_map;
3353 for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) { 3368 for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) {
3354 if (hotkey_keycode_map[i] != KEY_RESERVED) { 3369 if (hotkey_keycode_map[i] != KEY_RESERVED) {
3355 set_bit(hotkey_keycode_map[i], 3370 input_set_capability(tpacpi_inputdev, EV_KEY,
3356 tpacpi_inputdev->keybit); 3371 hotkey_keycode_map[i]);
3357 } else { 3372 } else {
3358 if (i < sizeof(hotkey_reserved_mask)*8) 3373 if (i < sizeof(hotkey_reserved_mask)*8)
3359 hotkey_reserved_mask |= 1 << i; 3374 hotkey_reserved_mask |= 1 << i;
@@ -3361,12 +3376,14 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3361 } 3376 }
3362 3377
3363 if (tp_features.hotkey_wlsw) { 3378 if (tp_features.hotkey_wlsw) {
3364 set_bit(EV_SW, tpacpi_inputdev->evbit); 3379 input_set_capability(tpacpi_inputdev, EV_SW, SW_RFKILL_ALL);
3365 set_bit(SW_RFKILL_ALL, tpacpi_inputdev->swbit); 3380 input_report_switch(tpacpi_inputdev,
3381 SW_RFKILL_ALL, radiosw_state);
3366 } 3382 }
3367 if (tp_features.hotkey_tablet) { 3383 if (tp_features.hotkey_tablet) {
3368 set_bit(EV_SW, tpacpi_inputdev->evbit); 3384 input_set_capability(tpacpi_inputdev, EV_SW, SW_TABLET_MODE);
3369 set_bit(SW_TABLET_MODE, tpacpi_inputdev->swbit); 3385 input_report_switch(tpacpi_inputdev,
3386 SW_TABLET_MODE, tabletsw_state);
3370 } 3387 }
3371 3388
3372 /* Do not issue duplicate brightness change events to 3389 /* Do not issue duplicate brightness change events to
@@ -3433,8 +3450,6 @@ static int __init hotkey_init(struct ibm_init_struct *iibm)
3433 tpacpi_inputdev->close = &hotkey_inputdev_close; 3450 tpacpi_inputdev->close = &hotkey_inputdev_close;
3434 3451
3435 hotkey_poll_setup_safe(true); 3452 hotkey_poll_setup_safe(true);
3436 tpacpi_send_radiosw_update();
3437 tpacpi_input_send_tabletsw();
3438 3453
3439 return 0; 3454 return 0;
3440 3455
@@ -3542,49 +3557,57 @@ static bool hotkey_notify_usrevent(const u32 hkey,
3542 } 3557 }
3543} 3558}
3544 3559
3560static void thermal_dump_all_sensors(void);
3561
3545static bool hotkey_notify_thermal(const u32 hkey, 3562static bool hotkey_notify_thermal(const u32 hkey,
3546 bool *send_acpi_ev, 3563 bool *send_acpi_ev,
3547 bool *ignore_acpi_ev) 3564 bool *ignore_acpi_ev)
3548{ 3565{
3566 bool known = true;
3567
3549 /* 0x6000-0x6FFF: thermal alarms */ 3568 /* 0x6000-0x6FFF: thermal alarms */
3550 *send_acpi_ev = true; 3569 *send_acpi_ev = true;
3551 *ignore_acpi_ev = false; 3570 *ignore_acpi_ev = false;
3552 3571
3553 switch (hkey) { 3572 switch (hkey) {
3573 case TP_HKEY_EV_THM_TABLE_CHANGED:
3574 printk(TPACPI_INFO
3575 "EC reports that Thermal Table has changed\n");
3576 /* recommended action: do nothing, we don't have
3577 * Lenovo ATM information */
3578 return true;
3554 case TP_HKEY_EV_ALARM_BAT_HOT: 3579 case TP_HKEY_EV_ALARM_BAT_HOT:
3555 printk(TPACPI_CRIT 3580 printk(TPACPI_CRIT
3556 "THERMAL ALARM: battery is too hot!\n"); 3581 "THERMAL ALARM: battery is too hot!\n");
3557 /* recommended action: warn user through gui */ 3582 /* recommended action: warn user through gui */
3558 return true; 3583 break;
3559 case TP_HKEY_EV_ALARM_BAT_XHOT: 3584 case TP_HKEY_EV_ALARM_BAT_XHOT:
3560 printk(TPACPI_ALERT 3585 printk(TPACPI_ALERT
3561 "THERMAL EMERGENCY: battery is extremely hot!\n"); 3586 "THERMAL EMERGENCY: battery is extremely hot!\n");
3562 /* recommended action: immediate sleep/hibernate */ 3587 /* recommended action: immediate sleep/hibernate */
3563 return true; 3588 break;
3564 case TP_HKEY_EV_ALARM_SENSOR_HOT: 3589 case TP_HKEY_EV_ALARM_SENSOR_HOT:
3565 printk(TPACPI_CRIT 3590 printk(TPACPI_CRIT
3566 "THERMAL ALARM: " 3591 "THERMAL ALARM: "
3567 "a sensor reports something is too hot!\n"); 3592 "a sensor reports something is too hot!\n");
3568 /* recommended action: warn user through gui, that */ 3593 /* recommended action: warn user through gui, that */
3569 /* some internal component is too hot */ 3594 /* some internal component is too hot */
3570 return true; 3595 break;
3571 case TP_HKEY_EV_ALARM_SENSOR_XHOT: 3596 case TP_HKEY_EV_ALARM_SENSOR_XHOT:
3572 printk(TPACPI_ALERT 3597 printk(TPACPI_ALERT
3573 "THERMAL EMERGENCY: " 3598 "THERMAL EMERGENCY: "
3574 "a sensor reports something is extremely hot!\n"); 3599 "a sensor reports something is extremely hot!\n");
3575 /* recommended action: immediate sleep/hibernate */ 3600 /* recommended action: immediate sleep/hibernate */
3576 return true; 3601 break;
3577 case TP_HKEY_EV_THM_TABLE_CHANGED:
3578 printk(TPACPI_INFO
3579 "EC reports that Thermal Table has changed\n");
3580 /* recommended action: do nothing, we don't have
3581 * Lenovo ATM information */
3582 return true;
3583 default: 3602 default:
3584 printk(TPACPI_ALERT 3603 printk(TPACPI_ALERT
3585 "THERMAL ALERT: unknown thermal alarm received\n"); 3604 "THERMAL ALERT: unknown thermal alarm received\n");
3586 return false; 3605 known = false;
3587 } 3606 }
3607
3608 thermal_dump_all_sensors();
3609
3610 return known;
3588} 3611}
3589 3612
3590static void hotkey_notify(struct ibm_struct *ibm, u32 event) 3613static void hotkey_notify(struct ibm_struct *ibm, u32 event)
@@ -3727,14 +3750,13 @@ static void hotkey_resume(void)
3727} 3750}
3728 3751
3729/* procfs -------------------------------------------------------------- */ 3752/* procfs -------------------------------------------------------------- */
3730static int hotkey_read(char *p) 3753static int hotkey_read(struct seq_file *m)
3731{ 3754{
3732 int res, status; 3755 int res, status;
3733 int len = 0;
3734 3756
3735 if (!tp_features.hotkey) { 3757 if (!tp_features.hotkey) {
3736 len += sprintf(p + len, "status:\t\tnot supported\n"); 3758 seq_printf(m, "status:\t\tnot supported\n");
3737 return len; 3759 return 0;
3738 } 3760 }
3739 3761
3740 if (mutex_lock_killable(&hotkey_mutex)) 3762 if (mutex_lock_killable(&hotkey_mutex))
@@ -3746,17 +3768,16 @@ static int hotkey_read(char *p)
3746 if (res) 3768 if (res)
3747 return res; 3769 return res;
3748 3770
3749 len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0)); 3771 seq_printf(m, "status:\t\t%s\n", enabled(status, 0));
3750 if (hotkey_all_mask) { 3772 if (hotkey_all_mask) {
3751 len += sprintf(p + len, "mask:\t\t0x%08x\n", hotkey_user_mask); 3773 seq_printf(m, "mask:\t\t0x%08x\n", hotkey_user_mask);
3752 len += sprintf(p + len, 3774 seq_printf(m, "commands:\tenable, disable, reset, <mask>\n");
3753 "commands:\tenable, disable, reset, <mask>\n");
3754 } else { 3775 } else {
3755 len += sprintf(p + len, "mask:\t\tnot supported\n"); 3776 seq_printf(m, "mask:\t\tnot supported\n");
3756 len += sprintf(p + len, "commands:\tenable, disable, reset\n"); 3777 seq_printf(m, "commands:\tenable, disable, reset\n");
3757 } 3778 }
3758 3779
3759 return len; 3780 return 0;
3760} 3781}
3761 3782
3762static void hotkey_enabledisable_warn(bool enable) 3783static void hotkey_enabledisable_warn(bool enable)
@@ -3863,15 +3884,6 @@ enum {
3863 3884
3864#define TPACPI_RFK_BLUETOOTH_SW_NAME "tpacpi_bluetooth_sw" 3885#define TPACPI_RFK_BLUETOOTH_SW_NAME "tpacpi_bluetooth_sw"
3865 3886
3866static void bluetooth_suspend(pm_message_t state)
3867{
3868 /* Try to make sure radio will resume powered off */
3869 if (!acpi_evalf(NULL, NULL, "\\BLTH", "vd",
3870 TP_ACPI_BLTH_PWR_OFF_ON_RESUME))
3871 vdbg_printk(TPACPI_DBG_RFKILL,
3872 "bluetooth power down on resume request failed\n");
3873}
3874
3875static int bluetooth_get_status(void) 3887static int bluetooth_get_status(void)
3876{ 3888{
3877 int status; 3889 int status;
@@ -3905,10 +3917,9 @@ static int bluetooth_set_status(enum tpacpi_rfkill_state state)
3905#endif 3917#endif
3906 3918
3907 /* We make sure to keep TP_ACPI_BLUETOOTH_RESUMECTRL off */ 3919 /* We make sure to keep TP_ACPI_BLUETOOTH_RESUMECTRL off */
3920 status = TP_ACPI_BLUETOOTH_RESUMECTRL;
3908 if (state == TPACPI_RFK_RADIO_ON) 3921 if (state == TPACPI_RFK_RADIO_ON)
3909 status = TP_ACPI_BLUETOOTH_RADIOSSW; 3922 status |= TP_ACPI_BLUETOOTH_RADIOSSW;
3910 else
3911 status = 0;
3912 3923
3913 if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status)) 3924 if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status))
3914 return -EIO; 3925 return -EIO;
@@ -4032,9 +4043,9 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm)
4032} 4043}
4033 4044
4034/* procfs -------------------------------------------------------------- */ 4045/* procfs -------------------------------------------------------------- */
4035static int bluetooth_read(char *p) 4046static int bluetooth_read(struct seq_file *m)
4036{ 4047{
4037 return tpacpi_rfk_procfs_read(TPACPI_RFK_BLUETOOTH_SW_ID, p); 4048 return tpacpi_rfk_procfs_read(TPACPI_RFK_BLUETOOTH_SW_ID, m);
4038} 4049}
4039 4050
4040static int bluetooth_write(char *buf) 4051static int bluetooth_write(char *buf)
@@ -4047,7 +4058,6 @@ static struct ibm_struct bluetooth_driver_data = {
4047 .read = bluetooth_read, 4058 .read = bluetooth_read,
4048 .write = bluetooth_write, 4059 .write = bluetooth_write,
4049 .exit = bluetooth_exit, 4060 .exit = bluetooth_exit,
4050 .suspend = bluetooth_suspend,
4051 .shutdown = bluetooth_shutdown, 4061 .shutdown = bluetooth_shutdown,
4052}; 4062};
4053 4063
@@ -4065,15 +4075,6 @@ enum {
4065 4075
4066#define TPACPI_RFK_WWAN_SW_NAME "tpacpi_wwan_sw" 4076#define TPACPI_RFK_WWAN_SW_NAME "tpacpi_wwan_sw"
4067 4077
4068static void wan_suspend(pm_message_t state)
4069{
4070 /* Try to make sure radio will resume powered off */
4071 if (!acpi_evalf(NULL, NULL, "\\WGSV", "qvd",
4072 TP_ACPI_WGSV_PWR_OFF_ON_RESUME))
4073 vdbg_printk(TPACPI_DBG_RFKILL,
4074 "WWAN power down on resume request failed\n");
4075}
4076
4077static int wan_get_status(void) 4078static int wan_get_status(void)
4078{ 4079{
4079 int status; 4080 int status;
@@ -4106,11 +4107,10 @@ static int wan_set_status(enum tpacpi_rfkill_state state)
4106 } 4107 }
4107#endif 4108#endif
4108 4109
4109 /* We make sure to keep TP_ACPI_WANCARD_RESUMECTRL off */ 4110 /* We make sure to set TP_ACPI_WANCARD_RESUMECTRL */
4111 status = TP_ACPI_WANCARD_RESUMECTRL;
4110 if (state == TPACPI_RFK_RADIO_ON) 4112 if (state == TPACPI_RFK_RADIO_ON)
4111 status = TP_ACPI_WANCARD_RADIOSSW; 4113 status |= TP_ACPI_WANCARD_RADIOSSW;
4112 else
4113 status = 0;
4114 4114
4115 if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status)) 4115 if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status))
4116 return -EIO; 4116 return -EIO;
@@ -4233,9 +4233,9 @@ static int __init wan_init(struct ibm_init_struct *iibm)
4233} 4233}
4234 4234
4235/* procfs -------------------------------------------------------------- */ 4235/* procfs -------------------------------------------------------------- */
4236static int wan_read(char *p) 4236static int wan_read(struct seq_file *m)
4237{ 4237{
4238 return tpacpi_rfk_procfs_read(TPACPI_RFK_WWAN_SW_ID, p); 4238 return tpacpi_rfk_procfs_read(TPACPI_RFK_WWAN_SW_ID, m);
4239} 4239}
4240 4240
4241static int wan_write(char *buf) 4241static int wan_write(char *buf)
@@ -4248,7 +4248,6 @@ static struct ibm_struct wan_driver_data = {
4248 .read = wan_read, 4248 .read = wan_read,
4249 .write = wan_write, 4249 .write = wan_write,
4250 .exit = wan_exit, 4250 .exit = wan_exit,
4251 .suspend = wan_suspend,
4252 .shutdown = wan_shutdown, 4251 .shutdown = wan_shutdown,
4253}; 4252};
4254 4253
@@ -4611,14 +4610,13 @@ static int video_expand_toggle(void)
4611 /* not reached */ 4610 /* not reached */
4612} 4611}
4613 4612
4614static int video_read(char *p) 4613static int video_read(struct seq_file *m)
4615{ 4614{
4616 int status, autosw; 4615 int status, autosw;
4617 int len = 0;
4618 4616
4619 if (video_supported == TPACPI_VIDEO_NONE) { 4617 if (video_supported == TPACPI_VIDEO_NONE) {
4620 len += sprintf(p + len, "status:\t\tnot supported\n"); 4618 seq_printf(m, "status:\t\tnot supported\n");
4621 return len; 4619 return 0;
4622 } 4620 }
4623 4621
4624 status = video_outputsw_get(); 4622 status = video_outputsw_get();
@@ -4629,20 +4627,20 @@ static int video_read(char *p)
4629 if (autosw < 0) 4627 if (autosw < 0)
4630 return autosw; 4628 return autosw;
4631 4629
4632 len += sprintf(p + len, "status:\t\tsupported\n"); 4630 seq_printf(m, "status:\t\tsupported\n");
4633 len += sprintf(p + len, "lcd:\t\t%s\n", enabled(status, 0)); 4631 seq_printf(m, "lcd:\t\t%s\n", enabled(status, 0));
4634 len += sprintf(p + len, "crt:\t\t%s\n", enabled(status, 1)); 4632 seq_printf(m, "crt:\t\t%s\n", enabled(status, 1));
4635 if (video_supported == TPACPI_VIDEO_NEW) 4633 if (video_supported == TPACPI_VIDEO_NEW)
4636 len += sprintf(p + len, "dvi:\t\t%s\n", enabled(status, 3)); 4634 seq_printf(m, "dvi:\t\t%s\n", enabled(status, 3));
4637 len += sprintf(p + len, "auto:\t\t%s\n", enabled(autosw, 0)); 4635 seq_printf(m, "auto:\t\t%s\n", enabled(autosw, 0));
4638 len += sprintf(p + len, "commands:\tlcd_enable, lcd_disable\n"); 4636 seq_printf(m, "commands:\tlcd_enable, lcd_disable\n");
4639 len += sprintf(p + len, "commands:\tcrt_enable, crt_disable\n"); 4637 seq_printf(m, "commands:\tcrt_enable, crt_disable\n");
4640 if (video_supported == TPACPI_VIDEO_NEW) 4638 if (video_supported == TPACPI_VIDEO_NEW)
4641 len += sprintf(p + len, "commands:\tdvi_enable, dvi_disable\n"); 4639 seq_printf(m, "commands:\tdvi_enable, dvi_disable\n");
4642 len += sprintf(p + len, "commands:\tauto_enable, auto_disable\n"); 4640 seq_printf(m, "commands:\tauto_enable, auto_disable\n");
4643 len += sprintf(p + len, "commands:\tvideo_switch, expand_toggle\n"); 4641 seq_printf(m, "commands:\tvideo_switch, expand_toggle\n");
4644 4642
4645 return len; 4643 return 0;
4646} 4644}
4647 4645
4648static int video_write(char *buf) 4646static int video_write(char *buf)
@@ -4834,25 +4832,24 @@ static void light_exit(void)
4834 flush_workqueue(tpacpi_wq); 4832 flush_workqueue(tpacpi_wq);
4835} 4833}
4836 4834
4837static int light_read(char *p) 4835static int light_read(struct seq_file *m)
4838{ 4836{
4839 int len = 0;
4840 int status; 4837 int status;
4841 4838
4842 if (!tp_features.light) { 4839 if (!tp_features.light) {
4843 len += sprintf(p + len, "status:\t\tnot supported\n"); 4840 seq_printf(m, "status:\t\tnot supported\n");
4844 } else if (!tp_features.light_status) { 4841 } else if (!tp_features.light_status) {
4845 len += sprintf(p + len, "status:\t\tunknown\n"); 4842 seq_printf(m, "status:\t\tunknown\n");
4846 len += sprintf(p + len, "commands:\ton, off\n"); 4843 seq_printf(m, "commands:\ton, off\n");
4847 } else { 4844 } else {
4848 status = light_get_status(); 4845 status = light_get_status();
4849 if (status < 0) 4846 if (status < 0)
4850 return status; 4847 return status;
4851 len += sprintf(p + len, "status:\t\t%s\n", onoff(status, 0)); 4848 seq_printf(m, "status:\t\t%s\n", onoff(status, 0));
4852 len += sprintf(p + len, "commands:\ton, off\n"); 4849 seq_printf(m, "commands:\ton, off\n");
4853 } 4850 }
4854 4851
4855 return len; 4852 return 0;
4856} 4853}
4857 4854
4858static int light_write(char *buf) 4855static int light_write(char *buf)
@@ -4930,20 +4927,18 @@ static void cmos_exit(void)
4930 device_remove_file(&tpacpi_pdev->dev, &dev_attr_cmos_command); 4927 device_remove_file(&tpacpi_pdev->dev, &dev_attr_cmos_command);
4931} 4928}
4932 4929
4933static int cmos_read(char *p) 4930static int cmos_read(struct seq_file *m)
4934{ 4931{
4935 int len = 0;
4936
4937 /* cmos not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p, 4932 /* cmos not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p,
4938 R30, R31, T20-22, X20-21 */ 4933 R30, R31, T20-22, X20-21 */
4939 if (!cmos_handle) 4934 if (!cmos_handle)
4940 len += sprintf(p + len, "status:\t\tnot supported\n"); 4935 seq_printf(m, "status:\t\tnot supported\n");
4941 else { 4936 else {
4942 len += sprintf(p + len, "status:\t\tsupported\n"); 4937 seq_printf(m, "status:\t\tsupported\n");
4943 len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-21)\n"); 4938 seq_printf(m, "commands:\t<cmd> (<cmd> is 0-21)\n");
4944 } 4939 }
4945 4940
4946 return len; 4941 return 0;
4947} 4942}
4948 4943
4949static int cmos_write(char *buf) 4944static int cmos_write(char *buf)
@@ -5318,15 +5313,13 @@ static int __init led_init(struct ibm_init_struct *iibm)
5318 ((s) == TPACPI_LED_OFF ? "off" : \ 5313 ((s) == TPACPI_LED_OFF ? "off" : \
5319 ((s) == TPACPI_LED_ON ? "on" : "blinking")) 5314 ((s) == TPACPI_LED_ON ? "on" : "blinking"))
5320 5315
5321static int led_read(char *p) 5316static int led_read(struct seq_file *m)
5322{ 5317{
5323 int len = 0;
5324
5325 if (!led_supported) { 5318 if (!led_supported) {
5326 len += sprintf(p + len, "status:\t\tnot supported\n"); 5319 seq_printf(m, "status:\t\tnot supported\n");
5327 return len; 5320 return 0;
5328 } 5321 }
5329 len += sprintf(p + len, "status:\t\tsupported\n"); 5322 seq_printf(m, "status:\t\tsupported\n");
5330 5323
5331 if (led_supported == TPACPI_LED_570) { 5324 if (led_supported == TPACPI_LED_570) {
5332 /* 570 */ 5325 /* 570 */
@@ -5335,15 +5328,15 @@ static int led_read(char *p)
5335 status = led_get_status(i); 5328 status = led_get_status(i);
5336 if (status < 0) 5329 if (status < 0)
5337 return -EIO; 5330 return -EIO;
5338 len += sprintf(p + len, "%d:\t\t%s\n", 5331 seq_printf(m, "%d:\t\t%s\n",
5339 i, str_led_status(status)); 5332 i, str_led_status(status));
5340 } 5333 }
5341 } 5334 }
5342 5335
5343 len += sprintf(p + len, "commands:\t" 5336 seq_printf(m, "commands:\t"
5344 "<led> on, <led> off, <led> blink (<led> is 0-15)\n"); 5337 "<led> on, <led> off, <led> blink (<led> is 0-15)\n");
5345 5338
5346 return len; 5339 return 0;
5347} 5340}
5348 5341
5349static int led_write(char *buf) 5342static int led_write(char *buf)
@@ -5416,18 +5409,16 @@ static int __init beep_init(struct ibm_init_struct *iibm)
5416 return (beep_handle)? 0 : 1; 5409 return (beep_handle)? 0 : 1;
5417} 5410}
5418 5411
5419static int beep_read(char *p) 5412static int beep_read(struct seq_file *m)
5420{ 5413{
5421 int len = 0;
5422
5423 if (!beep_handle) 5414 if (!beep_handle)
5424 len += sprintf(p + len, "status:\t\tnot supported\n"); 5415 seq_printf(m, "status:\t\tnot supported\n");
5425 else { 5416 else {
5426 len += sprintf(p + len, "status:\t\tsupported\n"); 5417 seq_printf(m, "status:\t\tsupported\n");
5427 len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-17)\n"); 5418 seq_printf(m, "commands:\t<cmd> (<cmd> is 0-17)\n");
5428 } 5419 }
5429 5420
5430 return len; 5421 return 0;
5431} 5422}
5432 5423
5433static int beep_write(char *buf) 5424static int beep_write(char *buf)
@@ -5480,8 +5471,11 @@ enum { /* TPACPI_THERMAL_TPEC_* */
5480 TP_EC_THERMAL_TMP0 = 0x78, /* ACPI EC regs TMP 0..7 */ 5471 TP_EC_THERMAL_TMP0 = 0x78, /* ACPI EC regs TMP 0..7 */
5481 TP_EC_THERMAL_TMP8 = 0xC0, /* ACPI EC regs TMP 8..15 */ 5472 TP_EC_THERMAL_TMP8 = 0xC0, /* ACPI EC regs TMP 8..15 */
5482 TP_EC_THERMAL_TMP_NA = -128, /* ACPI EC sensor not available */ 5473 TP_EC_THERMAL_TMP_NA = -128, /* ACPI EC sensor not available */
5474
5475 TPACPI_THERMAL_SENSOR_NA = -128000, /* Sensor not available */
5483}; 5476};
5484 5477
5478
5485#define TPACPI_MAX_THERMAL_SENSORS 16 /* Max thermal sensors supported */ 5479#define TPACPI_MAX_THERMAL_SENSORS 16 /* Max thermal sensors supported */
5486struct ibm_thermal_sensors_struct { 5480struct ibm_thermal_sensors_struct {
5487 s32 temp[TPACPI_MAX_THERMAL_SENSORS]; 5481 s32 temp[TPACPI_MAX_THERMAL_SENSORS];
@@ -5571,6 +5565,28 @@ static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s)
5571 return n; 5565 return n;
5572} 5566}
5573 5567
5568static void thermal_dump_all_sensors(void)
5569{
5570 int n, i;
5571 struct ibm_thermal_sensors_struct t;
5572
5573 n = thermal_get_sensors(&t);
5574 if (n <= 0)
5575 return;
5576
5577 printk(TPACPI_NOTICE
5578 "temperatures (Celsius):");
5579
5580 for (i = 0; i < n; i++) {
5581 if (t.temp[i] != TPACPI_THERMAL_SENSOR_NA)
5582 printk(KERN_CONT " %d", (int)(t.temp[i] / 1000));
5583 else
5584 printk(KERN_CONT " N/A");
5585 }
5586
5587 printk(KERN_CONT "\n");
5588}
5589
5574/* sysfs temp##_input -------------------------------------------------- */ 5590/* sysfs temp##_input -------------------------------------------------- */
5575 5591
5576static ssize_t thermal_temp_input_show(struct device *dev, 5592static ssize_t thermal_temp_input_show(struct device *dev,
@@ -5586,7 +5602,7 @@ static ssize_t thermal_temp_input_show(struct device *dev,
5586 res = thermal_get_sensor(idx, &value); 5602 res = thermal_get_sensor(idx, &value);
5587 if (res) 5603 if (res)
5588 return res; 5604 return res;
5589 if (value == TP_EC_THERMAL_TMP_NA * 1000) 5605 if (value == TPACPI_THERMAL_SENSOR_NA)
5590 return -ENXIO; 5606 return -ENXIO;
5591 5607
5592 return snprintf(buf, PAGE_SIZE, "%d\n", value); 5608 return snprintf(buf, PAGE_SIZE, "%d\n", value);
@@ -5763,9 +5779,8 @@ static void thermal_exit(void)
5763 } 5779 }
5764} 5780}
5765 5781
5766static int thermal_read(char *p) 5782static int thermal_read(struct seq_file *m)
5767{ 5783{
5768 int len = 0;
5769 int n, i; 5784 int n, i;
5770 struct ibm_thermal_sensors_struct t; 5785 struct ibm_thermal_sensors_struct t;
5771 5786
@@ -5773,16 +5788,16 @@ static int thermal_read(char *p)
5773 if (unlikely(n < 0)) 5788 if (unlikely(n < 0))
5774 return n; 5789 return n;
5775 5790
5776 len += sprintf(p + len, "temperatures:\t"); 5791 seq_printf(m, "temperatures:\t");
5777 5792
5778 if (n > 0) { 5793 if (n > 0) {
5779 for (i = 0; i < (n - 1); i++) 5794 for (i = 0; i < (n - 1); i++)
5780 len += sprintf(p + len, "%d ", t.temp[i] / 1000); 5795 seq_printf(m, "%d ", t.temp[i] / 1000);
5781 len += sprintf(p + len, "%d\n", t.temp[i] / 1000); 5796 seq_printf(m, "%d\n", t.temp[i] / 1000);
5782 } else 5797 } else
5783 len += sprintf(p + len, "not supported\n"); 5798 seq_printf(m, "not supported\n");
5784 5799
5785 return len; 5800 return 0;
5786} 5801}
5787 5802
5788static struct ibm_struct thermal_driver_data = { 5803static struct ibm_struct thermal_driver_data = {
@@ -5797,39 +5812,38 @@ static struct ibm_struct thermal_driver_data = {
5797 5812
5798static u8 ecdump_regs[256]; 5813static u8 ecdump_regs[256];
5799 5814
5800static int ecdump_read(char *p) 5815static int ecdump_read(struct seq_file *m)
5801{ 5816{
5802 int len = 0;
5803 int i, j; 5817 int i, j;
5804 u8 v; 5818 u8 v;
5805 5819
5806 len += sprintf(p + len, "EC " 5820 seq_printf(m, "EC "
5807 " +00 +01 +02 +03 +04 +05 +06 +07" 5821 " +00 +01 +02 +03 +04 +05 +06 +07"
5808 " +08 +09 +0a +0b +0c +0d +0e +0f\n"); 5822 " +08 +09 +0a +0b +0c +0d +0e +0f\n");
5809 for (i = 0; i < 256; i += 16) { 5823 for (i = 0; i < 256; i += 16) {
5810 len += sprintf(p + len, "EC 0x%02x:", i); 5824 seq_printf(m, "EC 0x%02x:", i);
5811 for (j = 0; j < 16; j++) { 5825 for (j = 0; j < 16; j++) {
5812 if (!acpi_ec_read(i + j, &v)) 5826 if (!acpi_ec_read(i + j, &v))
5813 break; 5827 break;
5814 if (v != ecdump_regs[i + j]) 5828 if (v != ecdump_regs[i + j])
5815 len += sprintf(p + len, " *%02x", v); 5829 seq_printf(m, " *%02x", v);
5816 else 5830 else
5817 len += sprintf(p + len, " %02x", v); 5831 seq_printf(m, " %02x", v);
5818 ecdump_regs[i + j] = v; 5832 ecdump_regs[i + j] = v;
5819 } 5833 }
5820 len += sprintf(p + len, "\n"); 5834 seq_putc(m, '\n');
5821 if (j != 16) 5835 if (j != 16)
5822 break; 5836 break;
5823 } 5837 }
5824 5838
5825 /* These are way too dangerous to advertise openly... */ 5839 /* These are way too dangerous to advertise openly... */
5826#if 0 5840#if 0
5827 len += sprintf(p + len, "commands:\t0x<offset> 0x<value>" 5841 seq_printf(m, "commands:\t0x<offset> 0x<value>"
5828 " (<offset> is 00-ff, <value> is 00-ff)\n"); 5842 " (<offset> is 00-ff, <value> is 00-ff)\n");
5829 len += sprintf(p + len, "commands:\t0x<offset> <value> " 5843 seq_printf(m, "commands:\t0x<offset> <value> "
5830 " (<offset> is 00-ff, <value> is 0-255)\n"); 5844 " (<offset> is 00-ff, <value> is 0-255)\n");
5831#endif 5845#endif
5832 return len; 5846 return 0;
5833} 5847}
5834 5848
5835static int ecdump_write(char *buf) 5849static int ecdump_write(char *buf)
@@ -6092,6 +6106,12 @@ static int brightness_get(struct backlight_device *bd)
6092 return status & TP_EC_BACKLIGHT_LVLMSK; 6106 return status & TP_EC_BACKLIGHT_LVLMSK;
6093} 6107}
6094 6108
6109static void tpacpi_brightness_notify_change(void)
6110{
6111 backlight_force_update(ibm_backlight_device,
6112 BACKLIGHT_UPDATE_HOTKEY);
6113}
6114
6095static struct backlight_ops ibm_backlight_data = { 6115static struct backlight_ops ibm_backlight_data = {
6096 .get_brightness = brightness_get, 6116 .get_brightness = brightness_get,
6097 .update_status = brightness_update_status, 6117 .update_status = brightness_update_status,
@@ -6120,8 +6140,8 @@ static const struct tpacpi_quirk brightness_quirk_table[] __initconst = {
6120 6140
6121 /* Models with Intel Extreme Graphics 2 */ 6141 /* Models with Intel Extreme Graphics 2 */
6122 TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_NOEC), 6142 TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_NOEC),
6123 TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC), 6143 TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
6124 TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC), 6144 TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC),
6125 6145
6126 /* Models with Intel GMA900 */ 6146 /* Models with Intel GMA900 */
6127 TPACPI_Q_IBM('7', '0', TPACPI_BRGHT_Q_NOEC), /* T43, R52 */ 6147 TPACPI_Q_IBM('7', '0', TPACPI_BRGHT_Q_NOEC), /* T43, R52 */
@@ -6246,6 +6266,12 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
6246 ibm_backlight_device->props.brightness = b & TP_EC_BACKLIGHT_LVLMSK; 6266 ibm_backlight_device->props.brightness = b & TP_EC_BACKLIGHT_LVLMSK;
6247 backlight_update_status(ibm_backlight_device); 6267 backlight_update_status(ibm_backlight_device);
6248 6268
6269 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_BRGHT,
6270 "brightness: registering brightness hotkeys "
6271 "as change notification\n");
6272 tpacpi_hotkey_driver_mask_set(hotkey_driver_mask
6273 | TP_ACPI_HKEY_BRGHTUP_MASK
6274 | TP_ACPI_HKEY_BRGHTDWN_MASK);;
6249 return 0; 6275 return 0;
6250} 6276}
6251 6277
@@ -6270,23 +6296,22 @@ static void brightness_exit(void)
6270 tpacpi_brightness_checkpoint_nvram(); 6296 tpacpi_brightness_checkpoint_nvram();
6271} 6297}
6272 6298
6273static int brightness_read(char *p) 6299static int brightness_read(struct seq_file *m)
6274{ 6300{
6275 int len = 0;
6276 int level; 6301 int level;
6277 6302
6278 level = brightness_get(NULL); 6303 level = brightness_get(NULL);
6279 if (level < 0) { 6304 if (level < 0) {
6280 len += sprintf(p + len, "level:\t\tunreadable\n"); 6305 seq_printf(m, "level:\t\tunreadable\n");
6281 } else { 6306 } else {
6282 len += sprintf(p + len, "level:\t\t%d\n", level); 6307 seq_printf(m, "level:\t\t%d\n", level);
6283 len += sprintf(p + len, "commands:\tup, down\n"); 6308 seq_printf(m, "commands:\tup, down\n");
6284 len += sprintf(p + len, "commands:\tlevel <level>" 6309 seq_printf(m, "commands:\tlevel <level>"
6285 " (<level> is 0-%d)\n", 6310 " (<level> is 0-%d)\n",
6286 (tp_features.bright_16levels) ? 15 : 7); 6311 (tp_features.bright_16levels) ? 15 : 7);
6287 } 6312 }
6288 6313
6289 return len; 6314 return 0;
6290} 6315}
6291 6316
6292static int brightness_write(char *buf) 6317static int brightness_write(char *buf)
@@ -6322,6 +6347,9 @@ static int brightness_write(char *buf)
6322 * Doing it this way makes the syscall restartable in case of EINTR 6347 * Doing it this way makes the syscall restartable in case of EINTR
6323 */ 6348 */
6324 rc = brightness_set(level); 6349 rc = brightness_set(level);
6350 if (!rc && ibm_backlight_device)
6351 backlight_force_update(ibm_backlight_device,
6352 BACKLIGHT_UPDATE_SYSFS);
6325 return (rc == -EINTR)? -ERESTARTSYS : rc; 6353 return (rc == -EINTR)? -ERESTARTSYS : rc;
6326} 6354}
6327 6355
@@ -6338,99 +6366,654 @@ static struct ibm_struct brightness_driver_data = {
6338 * Volume subdriver 6366 * Volume subdriver
6339 */ 6367 */
6340 6368
6341static int volume_offset = 0x30; 6369/*
6370 * IBM ThinkPads have a simple volume controller with MUTE gating.
6371 * Very early Lenovo ThinkPads follow the IBM ThinkPad spec.
6372 *
6373 * Since the *61 series (and probably also the later *60 series), Lenovo
6374 * ThinkPads only implement the MUTE gate.
6375 *
6376 * EC register 0x30
6377 * Bit 6: MUTE (1 mutes sound)
6378 * Bit 3-0: Volume
6379 * Other bits should be zero as far as we know.
6380 *
6381 * This is also stored in CMOS NVRAM, byte 0x60, bit 6 (MUTE), and
6382 * bits 3-0 (volume). Other bits in NVRAM may have other functions,
6383 * such as bit 7 which is used to detect repeated presses of MUTE,
6384 * and we leave them unchanged.
6385 */
6386
6387#define TPACPI_ALSA_DRVNAME "ThinkPad EC"
6388#define TPACPI_ALSA_SHRTNAME "ThinkPad Console Audio Control"
6389#define TPACPI_ALSA_MIXERNAME TPACPI_ALSA_SHRTNAME
6390
6391static int alsa_index = SNDRV_DEFAULT_IDX1;
6392static char *alsa_id = "ThinkPadEC";
6393static int alsa_enable = SNDRV_DEFAULT_ENABLE1;
6394
6395struct tpacpi_alsa_data {
6396 struct snd_card *card;
6397 struct snd_ctl_elem_id *ctl_mute_id;
6398 struct snd_ctl_elem_id *ctl_vol_id;
6399};
6400
6401static struct snd_card *alsa_card;
6402
6403enum {
6404 TP_EC_AUDIO = 0x30,
6405
6406 /* TP_EC_AUDIO bits */
6407 TP_EC_AUDIO_MUTESW = 6,
6408
6409 /* TP_EC_AUDIO bitmasks */
6410 TP_EC_AUDIO_LVL_MSK = 0x0F,
6411 TP_EC_AUDIO_MUTESW_MSK = (1 << TP_EC_AUDIO_MUTESW),
6412
6413 /* Maximum volume */
6414 TP_EC_VOLUME_MAX = 14,
6415};
6416
6417enum tpacpi_volume_access_mode {
6418 TPACPI_VOL_MODE_AUTO = 0, /* Not implemented yet */
6419 TPACPI_VOL_MODE_EC, /* Pure EC control */
6420 TPACPI_VOL_MODE_UCMS_STEP, /* UCMS step-based control: N/A */
6421 TPACPI_VOL_MODE_ECNVRAM, /* EC control w/ NVRAM store */
6422 TPACPI_VOL_MODE_MAX
6423};
6424
6425enum tpacpi_volume_capabilities {
6426 TPACPI_VOL_CAP_AUTO = 0, /* Use white/blacklist */
6427 TPACPI_VOL_CAP_VOLMUTE, /* Output vol and mute */
6428 TPACPI_VOL_CAP_MUTEONLY, /* Output mute only */
6429 TPACPI_VOL_CAP_MAX
6430};
6431
6432static enum tpacpi_volume_access_mode volume_mode =
6433 TPACPI_VOL_MODE_MAX;
6434
6435static enum tpacpi_volume_capabilities volume_capabilities;
6436static int volume_control_allowed;
6342 6437
6343static int volume_read(char *p) 6438/*
6439 * Used to syncronize writers to TP_EC_AUDIO and
6440 * TP_NVRAM_ADDR_MIXER, as we need to do read-modify-write
6441 */
6442static struct mutex volume_mutex;
6443
6444static void tpacpi_volume_checkpoint_nvram(void)
6344{ 6445{
6345 int len = 0; 6446 u8 lec = 0;
6346 u8 level; 6447 u8 b_nvram;
6448 u8 ec_mask;
6449
6450 if (volume_mode != TPACPI_VOL_MODE_ECNVRAM)
6451 return;
6452 if (!volume_control_allowed)
6453 return;
6454
6455 vdbg_printk(TPACPI_DBG_MIXER,
6456 "trying to checkpoint mixer state to NVRAM...\n");
6347 6457
6348 if (!acpi_ec_read(volume_offset, &level)) { 6458 if (tp_features.mixer_no_level_control)
6349 len += sprintf(p + len, "level:\t\tunreadable\n"); 6459 ec_mask = TP_EC_AUDIO_MUTESW_MSK;
6460 else
6461 ec_mask = TP_EC_AUDIO_MUTESW_MSK | TP_EC_AUDIO_LVL_MSK;
6462
6463 if (mutex_lock_killable(&volume_mutex) < 0)
6464 return;
6465
6466 if (unlikely(!acpi_ec_read(TP_EC_AUDIO, &lec)))
6467 goto unlock;
6468 lec &= ec_mask;
6469 b_nvram = nvram_read_byte(TP_NVRAM_ADDR_MIXER);
6470
6471 if (lec != (b_nvram & ec_mask)) {
6472 /* NVRAM needs update */
6473 b_nvram &= ~ec_mask;
6474 b_nvram |= lec;
6475 nvram_write_byte(b_nvram, TP_NVRAM_ADDR_MIXER);
6476 dbg_printk(TPACPI_DBG_MIXER,
6477 "updated NVRAM mixer status to 0x%02x (0x%02x)\n",
6478 (unsigned int) lec, (unsigned int) b_nvram);
6350 } else { 6479 } else {
6351 len += sprintf(p + len, "level:\t\t%d\n", level & 0xf); 6480 vdbg_printk(TPACPI_DBG_MIXER,
6352 len += sprintf(p + len, "mute:\t\t%s\n", onoff(level, 6)); 6481 "NVRAM mixer status already is 0x%02x (0x%02x)\n",
6353 len += sprintf(p + len, "commands:\tup, down, mute\n"); 6482 (unsigned int) lec, (unsigned int) b_nvram);
6354 len += sprintf(p + len, "commands:\tlevel <level>"
6355 " (<level> is 0-15)\n");
6356 } 6483 }
6357 6484
6358 return len; 6485unlock:
6486 mutex_unlock(&volume_mutex);
6359} 6487}
6360 6488
6361static int volume_write(char *buf) 6489static int volume_get_status_ec(u8 *status)
6362{ 6490{
6363 int cmos_cmd, inc, i; 6491 u8 s;
6364 u8 level, mute;
6365 int new_level, new_mute;
6366 char *cmd;
6367 6492
6368 while ((cmd = next_cmd(&buf))) { 6493 if (!acpi_ec_read(TP_EC_AUDIO, &s))
6369 if (!acpi_ec_read(volume_offset, &level)) 6494 return -EIO;
6370 return -EIO;
6371 new_mute = mute = level & 0x40;
6372 new_level = level = level & 0xf;
6373 6495
6374 if (strlencmp(cmd, "up") == 0) { 6496 *status = s;
6375 if (mute)
6376 new_mute = 0;
6377 else
6378 new_level = level == 15 ? 15 : level + 1;
6379 } else if (strlencmp(cmd, "down") == 0) {
6380 if (mute)
6381 new_mute = 0;
6382 else
6383 new_level = level == 0 ? 0 : level - 1;
6384 } else if (sscanf(cmd, "level %d", &new_level) == 1 &&
6385 new_level >= 0 && new_level <= 15) {
6386 /* new_level set */
6387 } else if (strlencmp(cmd, "mute") == 0) {
6388 new_mute = 0x40;
6389 } else
6390 return -EINVAL;
6391 6497
6392 if (new_level != level) { 6498 dbg_printk(TPACPI_DBG_MIXER, "status 0x%02x\n", s);
6393 /* mute doesn't change */
6394 6499
6395 cmos_cmd = (new_level > level) ? 6500 return 0;
6396 TP_CMOS_VOLUME_UP : TP_CMOS_VOLUME_DOWN; 6501}
6397 inc = new_level > level ? 1 : -1;
6398 6502
6399 if (mute && (issue_thinkpad_cmos_command(cmos_cmd) || 6503static int volume_get_status(u8 *status)
6400 !acpi_ec_write(volume_offset, level))) 6504{
6401 return -EIO; 6505 return volume_get_status_ec(status);
6506}
6402 6507
6403 for (i = level; i != new_level; i += inc) 6508static int volume_set_status_ec(const u8 status)
6404 if (issue_thinkpad_cmos_command(cmos_cmd) || 6509{
6405 !acpi_ec_write(volume_offset, i + inc)) 6510 if (!acpi_ec_write(TP_EC_AUDIO, status))
6406 return -EIO; 6511 return -EIO;
6407 6512
6408 if (mute && 6513 dbg_printk(TPACPI_DBG_MIXER, "set EC mixer to 0x%02x\n", status);
6409 (issue_thinkpad_cmos_command(TP_CMOS_VOLUME_MUTE) || 6514
6410 !acpi_ec_write(volume_offset, new_level + mute))) { 6515 return 0;
6411 return -EIO; 6516}
6412 } 6517
6518static int volume_set_status(const u8 status)
6519{
6520 return volume_set_status_ec(status);
6521}
6522
6523static int volume_set_mute_ec(const bool mute)
6524{
6525 int rc;
6526 u8 s, n;
6527
6528 if (mutex_lock_killable(&volume_mutex) < 0)
6529 return -EINTR;
6530
6531 rc = volume_get_status_ec(&s);
6532 if (rc)
6533 goto unlock;
6534
6535 n = (mute) ? s | TP_EC_AUDIO_MUTESW_MSK :
6536 s & ~TP_EC_AUDIO_MUTESW_MSK;
6537
6538 if (n != s)
6539 rc = volume_set_status_ec(n);
6540
6541unlock:
6542 mutex_unlock(&volume_mutex);
6543 return rc;
6544}
6545
6546static int volume_set_mute(const bool mute)
6547{
6548 dbg_printk(TPACPI_DBG_MIXER, "trying to %smute\n",
6549 (mute) ? "" : "un");
6550 return volume_set_mute_ec(mute);
6551}
6552
6553static int volume_set_volume_ec(const u8 vol)
6554{
6555 int rc;
6556 u8 s, n;
6557
6558 if (vol > TP_EC_VOLUME_MAX)
6559 return -EINVAL;
6560
6561 if (mutex_lock_killable(&volume_mutex) < 0)
6562 return -EINTR;
6563
6564 rc = volume_get_status_ec(&s);
6565 if (rc)
6566 goto unlock;
6567
6568 n = (s & ~TP_EC_AUDIO_LVL_MSK) | vol;
6569
6570 if (n != s)
6571 rc = volume_set_status_ec(n);
6572
6573unlock:
6574 mutex_unlock(&volume_mutex);
6575 return rc;
6576}
6577
6578static int volume_set_volume(const u8 vol)
6579{
6580 dbg_printk(TPACPI_DBG_MIXER,
6581 "trying to set volume level to %hu\n", vol);
6582 return volume_set_volume_ec(vol);
6583}
6584
6585static void volume_alsa_notify_change(void)
6586{
6587 struct tpacpi_alsa_data *d;
6588
6589 if (alsa_card && alsa_card->private_data) {
6590 d = alsa_card->private_data;
6591 if (d->ctl_mute_id)
6592 snd_ctl_notify(alsa_card,
6593 SNDRV_CTL_EVENT_MASK_VALUE,
6594 d->ctl_mute_id);
6595 if (d->ctl_vol_id)
6596 snd_ctl_notify(alsa_card,
6597 SNDRV_CTL_EVENT_MASK_VALUE,
6598 d->ctl_vol_id);
6599 }
6600}
6601
6602static int volume_alsa_vol_info(struct snd_kcontrol *kcontrol,
6603 struct snd_ctl_elem_info *uinfo)
6604{
6605 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
6606 uinfo->count = 1;
6607 uinfo->value.integer.min = 0;
6608 uinfo->value.integer.max = TP_EC_VOLUME_MAX;
6609 return 0;
6610}
6611
6612static int volume_alsa_vol_get(struct snd_kcontrol *kcontrol,
6613 struct snd_ctl_elem_value *ucontrol)
6614{
6615 u8 s;
6616 int rc;
6617
6618 rc = volume_get_status(&s);
6619 if (rc < 0)
6620 return rc;
6621
6622 ucontrol->value.integer.value[0] = s & TP_EC_AUDIO_LVL_MSK;
6623 return 0;
6624}
6625
6626static int volume_alsa_vol_put(struct snd_kcontrol *kcontrol,
6627 struct snd_ctl_elem_value *ucontrol)
6628{
6629 return volume_set_volume(ucontrol->value.integer.value[0]);
6630}
6631
6632#define volume_alsa_mute_info snd_ctl_boolean_mono_info
6633
6634static int volume_alsa_mute_get(struct snd_kcontrol *kcontrol,
6635 struct snd_ctl_elem_value *ucontrol)
6636{
6637 u8 s;
6638 int rc;
6639
6640 rc = volume_get_status(&s);
6641 if (rc < 0)
6642 return rc;
6643
6644 ucontrol->value.integer.value[0] =
6645 (s & TP_EC_AUDIO_MUTESW_MSK) ? 0 : 1;
6646 return 0;
6647}
6648
6649static int volume_alsa_mute_put(struct snd_kcontrol *kcontrol,
6650 struct snd_ctl_elem_value *ucontrol)
6651{
6652 return volume_set_mute(!ucontrol->value.integer.value[0]);
6653}
6654
6655static struct snd_kcontrol_new volume_alsa_control_vol __devinitdata = {
6656 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6657 .name = "Console Playback Volume",
6658 .index = 0,
6659 .access = SNDRV_CTL_ELEM_ACCESS_READ,
6660 .info = volume_alsa_vol_info,
6661 .get = volume_alsa_vol_get,
6662};
6663
6664static struct snd_kcontrol_new volume_alsa_control_mute __devinitdata = {
6665 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
6666 .name = "Console Playback Switch",
6667 .index = 0,
6668 .access = SNDRV_CTL_ELEM_ACCESS_READ,
6669 .info = volume_alsa_mute_info,
6670 .get = volume_alsa_mute_get,
6671};
6672
6673static void volume_suspend(pm_message_t state)
6674{
6675 tpacpi_volume_checkpoint_nvram();
6676}
6677
6678static void volume_resume(void)
6679{
6680 volume_alsa_notify_change();
6681}
6682
6683static void volume_shutdown(void)
6684{
6685 tpacpi_volume_checkpoint_nvram();
6686}
6687
6688static void volume_exit(void)
6689{
6690 if (alsa_card) {
6691 snd_card_free(alsa_card);
6692 alsa_card = NULL;
6693 }
6694
6695 tpacpi_volume_checkpoint_nvram();
6696}
6697
6698static int __init volume_create_alsa_mixer(void)
6699{
6700 struct snd_card *card;
6701 struct tpacpi_alsa_data *data;
6702 struct snd_kcontrol *ctl_vol;
6703 struct snd_kcontrol *ctl_mute;
6704 int rc;
6705
6706 rc = snd_card_create(alsa_index, alsa_id, THIS_MODULE,
6707 sizeof(struct tpacpi_alsa_data), &card);
6708 if (rc < 0)
6709 return rc;
6710 if (!card)
6711 return -ENOMEM;
6712
6713 BUG_ON(!card->private_data);
6714 data = card->private_data;
6715 data->card = card;
6716
6717 strlcpy(card->driver, TPACPI_ALSA_DRVNAME,
6718 sizeof(card->driver));
6719 strlcpy(card->shortname, TPACPI_ALSA_SHRTNAME,
6720 sizeof(card->shortname));
6721 snprintf(card->mixername, sizeof(card->mixername), "ThinkPad EC %s",
6722 (thinkpad_id.ec_version_str) ?
6723 thinkpad_id.ec_version_str : "(unknown)");
6724 snprintf(card->longname, sizeof(card->longname),
6725 "%s at EC reg 0x%02x, fw %s", card->shortname, TP_EC_AUDIO,
6726 (thinkpad_id.ec_version_str) ?
6727 thinkpad_id.ec_version_str : "unknown");
6728
6729 if (volume_control_allowed) {
6730 volume_alsa_control_vol.put = volume_alsa_vol_put;
6731 volume_alsa_control_vol.access =
6732 SNDRV_CTL_ELEM_ACCESS_READWRITE;
6733
6734 volume_alsa_control_mute.put = volume_alsa_mute_put;
6735 volume_alsa_control_mute.access =
6736 SNDRV_CTL_ELEM_ACCESS_READWRITE;
6737 }
6738
6739 if (!tp_features.mixer_no_level_control) {
6740 ctl_vol = snd_ctl_new1(&volume_alsa_control_vol, NULL);
6741 rc = snd_ctl_add(card, ctl_vol);
6742 if (rc < 0) {
6743 printk(TPACPI_ERR
6744 "Failed to create ALSA volume control\n");
6745 goto err_out;
6413 } 6746 }
6747 data->ctl_vol_id = &ctl_vol->id;
6748 }
6414 6749
6415 if (new_mute != mute) { 6750 ctl_mute = snd_ctl_new1(&volume_alsa_control_mute, NULL);
6416 /* level doesn't change */ 6751 rc = snd_ctl_add(card, ctl_mute);
6752 if (rc < 0) {
6753 printk(TPACPI_ERR "Failed to create ALSA mute control\n");
6754 goto err_out;
6755 }
6756 data->ctl_mute_id = &ctl_mute->id;
6417 6757
6418 cmos_cmd = (new_mute) ? 6758 snd_card_set_dev(card, &tpacpi_pdev->dev);
6419 TP_CMOS_VOLUME_MUTE : TP_CMOS_VOLUME_UP; 6759 rc = snd_card_register(card);
6420 6760
6421 if (issue_thinkpad_cmos_command(cmos_cmd) || 6761err_out:
6422 !acpi_ec_write(volume_offset, level + new_mute)) 6762 if (rc < 0) {
6423 return -EIO; 6763 snd_card_free(card);
6764 card = NULL;
6765 }
6766
6767 alsa_card = card;
6768 return rc;
6769}
6770
6771#define TPACPI_VOL_Q_MUTEONLY 0x0001 /* Mute-only control available */
6772#define TPACPI_VOL_Q_LEVEL 0x0002 /* Volume control available */
6773
6774static const struct tpacpi_quirk volume_quirk_table[] __initconst = {
6775 /* Whitelist volume level on all IBM by default */
6776 { .vendor = PCI_VENDOR_ID_IBM,
6777 .bios = TPACPI_MATCH_ANY,
6778 .ec = TPACPI_MATCH_ANY,
6779 .quirks = TPACPI_VOL_Q_LEVEL },
6780
6781 /* Lenovo models with volume control (needs confirmation) */
6782 TPACPI_QEC_LNV('7', 'C', TPACPI_VOL_Q_LEVEL), /* R60/i */
6783 TPACPI_QEC_LNV('7', 'E', TPACPI_VOL_Q_LEVEL), /* R60e/i */
6784 TPACPI_QEC_LNV('7', '9', TPACPI_VOL_Q_LEVEL), /* T60/p */
6785 TPACPI_QEC_LNV('7', 'B', TPACPI_VOL_Q_LEVEL), /* X60/s */
6786 TPACPI_QEC_LNV('7', 'J', TPACPI_VOL_Q_LEVEL), /* X60t */
6787 TPACPI_QEC_LNV('7', '7', TPACPI_VOL_Q_LEVEL), /* Z60 */
6788 TPACPI_QEC_LNV('7', 'F', TPACPI_VOL_Q_LEVEL), /* Z61 */
6789
6790 /* Whitelist mute-only on all Lenovo by default */
6791 { .vendor = PCI_VENDOR_ID_LENOVO,
6792 .bios = TPACPI_MATCH_ANY,
6793 .ec = TPACPI_MATCH_ANY,
6794 .quirks = TPACPI_VOL_Q_MUTEONLY }
6795};
6796
6797static int __init volume_init(struct ibm_init_struct *iibm)
6798{
6799 unsigned long quirks;
6800 int rc;
6801
6802 vdbg_printk(TPACPI_DBG_INIT, "initializing volume subdriver\n");
6803
6804 mutex_init(&volume_mutex);
6805
6806 /*
6807 * Check for module parameter bogosity, note that we
6808 * init volume_mode to TPACPI_VOL_MODE_MAX in order to be
6809 * able to detect "unspecified"
6810 */
6811 if (volume_mode > TPACPI_VOL_MODE_MAX)
6812 return -EINVAL;
6813
6814 if (volume_mode == TPACPI_VOL_MODE_UCMS_STEP) {
6815 printk(TPACPI_ERR
6816 "UCMS step volume mode not implemented, "
6817 "please contact %s\n", TPACPI_MAIL);
6818 return 1;
6819 }
6820
6821 if (volume_capabilities >= TPACPI_VOL_CAP_MAX)
6822 return -EINVAL;
6823
6824 /*
6825 * The ALSA mixer is our primary interface.
6826 * When disabled, don't install the subdriver at all
6827 */
6828 if (!alsa_enable) {
6829 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
6830 "ALSA mixer disabled by parameter, "
6831 "not loading volume subdriver...\n");
6832 return 1;
6833 }
6834
6835 quirks = tpacpi_check_quirks(volume_quirk_table,
6836 ARRAY_SIZE(volume_quirk_table));
6837
6838 switch (volume_capabilities) {
6839 case TPACPI_VOL_CAP_AUTO:
6840 if (quirks & TPACPI_VOL_Q_MUTEONLY)
6841 tp_features.mixer_no_level_control = 1;
6842 else if (quirks & TPACPI_VOL_Q_LEVEL)
6843 tp_features.mixer_no_level_control = 0;
6844 else
6845 return 1; /* no mixer */
6846 break;
6847 case TPACPI_VOL_CAP_VOLMUTE:
6848 tp_features.mixer_no_level_control = 0;
6849 break;
6850 case TPACPI_VOL_CAP_MUTEONLY:
6851 tp_features.mixer_no_level_control = 1;
6852 break;
6853 default:
6854 return 1;
6855 }
6856
6857 if (volume_capabilities != TPACPI_VOL_CAP_AUTO)
6858 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
6859 "using user-supplied volume_capabilities=%d\n",
6860 volume_capabilities);
6861
6862 if (volume_mode == TPACPI_VOL_MODE_AUTO ||
6863 volume_mode == TPACPI_VOL_MODE_MAX) {
6864 volume_mode = TPACPI_VOL_MODE_ECNVRAM;
6865
6866 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
6867 "driver auto-selected volume_mode=%d\n",
6868 volume_mode);
6869 } else {
6870 dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
6871 "using user-supplied volume_mode=%d\n",
6872 volume_mode);
6873 }
6874
6875 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
6876 "mute is supported, volume control is %s\n",
6877 str_supported(!tp_features.mixer_no_level_control));
6878
6879 rc = volume_create_alsa_mixer();
6880 if (rc) {
6881 printk(TPACPI_ERR
6882 "Could not create the ALSA mixer interface\n");
6883 return rc;
6884 }
6885
6886 printk(TPACPI_INFO
6887 "Console audio control enabled, mode: %s\n",
6888 (volume_control_allowed) ?
6889 "override (read/write)" :
6890 "monitor (read only)");
6891
6892 vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_MIXER,
6893 "registering volume hotkeys as change notification\n");
6894 tpacpi_hotkey_driver_mask_set(hotkey_driver_mask
6895 | TP_ACPI_HKEY_VOLUP_MASK
6896 | TP_ACPI_HKEY_VOLDWN_MASK
6897 | TP_ACPI_HKEY_MUTE_MASK);
6898
6899 return 0;
6900}
6901
6902static int volume_read(struct seq_file *m)
6903{
6904 u8 status;
6905
6906 if (volume_get_status(&status) < 0) {
6907 seq_printf(m, "level:\t\tunreadable\n");
6908 } else {
6909 if (tp_features.mixer_no_level_control)
6910 seq_printf(m, "level:\t\tunsupported\n");
6911 else
6912 seq_printf(m, "level:\t\t%d\n",
6913 status & TP_EC_AUDIO_LVL_MSK);
6914
6915 seq_printf(m, "mute:\t\t%s\n",
6916 onoff(status, TP_EC_AUDIO_MUTESW));
6917
6918 if (volume_control_allowed) {
6919 seq_printf(m, "commands:\tunmute, mute\n");
6920 if (!tp_features.mixer_no_level_control) {
6921 seq_printf(m,
6922 "commands:\tup, down\n");
6923 seq_printf(m,
6924 "commands:\tlevel <level>"
6925 " (<level> is 0-%d)\n",
6926 TP_EC_VOLUME_MAX);
6927 }
6424 } 6928 }
6425 } 6929 }
6426 6930
6427 return 0; 6931 return 0;
6428} 6932}
6429 6933
6934static int volume_write(char *buf)
6935{
6936 u8 s;
6937 u8 new_level, new_mute;
6938 int l;
6939 char *cmd;
6940 int rc;
6941
6942 /*
6943 * We do allow volume control at driver startup, so that the
6944 * user can set initial state through the volume=... parameter hack.
6945 */
6946 if (!volume_control_allowed && tpacpi_lifecycle != TPACPI_LIFE_INIT) {
6947 if (unlikely(!tp_warned.volume_ctrl_forbidden)) {
6948 tp_warned.volume_ctrl_forbidden = 1;
6949 printk(TPACPI_NOTICE
6950 "Console audio control in monitor mode, "
6951 "changes are not allowed.\n");
6952 printk(TPACPI_NOTICE
6953 "Use the volume_control=1 module parameter "
6954 "to enable volume control\n");
6955 }
6956 return -EPERM;
6957 }
6958
6959 rc = volume_get_status(&s);
6960 if (rc < 0)
6961 return rc;
6962
6963 new_level = s & TP_EC_AUDIO_LVL_MSK;
6964 new_mute = s & TP_EC_AUDIO_MUTESW_MSK;
6965
6966 while ((cmd = next_cmd(&buf))) {
6967 if (!tp_features.mixer_no_level_control) {
6968 if (strlencmp(cmd, "up") == 0) {
6969 if (new_mute)
6970 new_mute = 0;
6971 else if (new_level < TP_EC_VOLUME_MAX)
6972 new_level++;
6973 continue;
6974 } else if (strlencmp(cmd, "down") == 0) {
6975 if (new_mute)
6976 new_mute = 0;
6977 else if (new_level > 0)
6978 new_level--;
6979 continue;
6980 } else if (sscanf(cmd, "level %u", &l) == 1 &&
6981 l >= 0 && l <= TP_EC_VOLUME_MAX) {
6982 new_level = l;
6983 continue;
6984 }
6985 }
6986 if (strlencmp(cmd, "mute") == 0)
6987 new_mute = TP_EC_AUDIO_MUTESW_MSK;
6988 else if (strlencmp(cmd, "unmute") == 0)
6989 new_mute = 0;
6990 else
6991 return -EINVAL;
6992 }
6993
6994 if (tp_features.mixer_no_level_control) {
6995 tpacpi_disclose_usertask("procfs volume", "%smute\n",
6996 new_mute ? "" : "un");
6997 rc = volume_set_mute(!!new_mute);
6998 } else {
6999 tpacpi_disclose_usertask("procfs volume",
7000 "%smute and set level to %d\n",
7001 new_mute ? "" : "un", new_level);
7002 rc = volume_set_status(new_mute | new_level);
7003 }
7004 volume_alsa_notify_change();
7005
7006 return (rc == -EINTR) ? -ERESTARTSYS : rc;
7007}
7008
6430static struct ibm_struct volume_driver_data = { 7009static struct ibm_struct volume_driver_data = {
6431 .name = "volume", 7010 .name = "volume",
6432 .read = volume_read, 7011 .read = volume_read,
6433 .write = volume_write, 7012 .write = volume_write,
7013 .exit = volume_exit,
7014 .suspend = volume_suspend,
7015 .resume = volume_resume,
7016 .shutdown = volume_shutdown,
6434}; 7017};
6435 7018
6436/************************************************************************* 7019/*************************************************************************
@@ -7507,9 +8090,8 @@ static void fan_resume(void)
7507 } 8090 }
7508} 8091}
7509 8092
7510static int fan_read(char *p) 8093static int fan_read(struct seq_file *m)
7511{ 8094{
7512 int len = 0;
7513 int rc; 8095 int rc;
7514 u8 status; 8096 u8 status;
7515 unsigned int speed = 0; 8097 unsigned int speed = 0;
@@ -7521,7 +8103,7 @@ static int fan_read(char *p)
7521 if (rc < 0) 8103 if (rc < 0)
7522 return rc; 8104 return rc;
7523 8105
7524 len += sprintf(p + len, "status:\t\t%s\n" 8106 seq_printf(m, "status:\t\t%s\n"
7525 "level:\t\t%d\n", 8107 "level:\t\t%d\n",
7526 (status != 0) ? "enabled" : "disabled", status); 8108 (status != 0) ? "enabled" : "disabled", status);
7527 break; 8109 break;
@@ -7532,54 +8114,54 @@ static int fan_read(char *p)
7532 if (rc < 0) 8114 if (rc < 0)
7533 return rc; 8115 return rc;
7534 8116
7535 len += sprintf(p + len, "status:\t\t%s\n", 8117 seq_printf(m, "status:\t\t%s\n",
7536 (status != 0) ? "enabled" : "disabled"); 8118 (status != 0) ? "enabled" : "disabled");
7537 8119
7538 rc = fan_get_speed(&speed); 8120 rc = fan_get_speed(&speed);
7539 if (rc < 0) 8121 if (rc < 0)
7540 return rc; 8122 return rc;
7541 8123
7542 len += sprintf(p + len, "speed:\t\t%d\n", speed); 8124 seq_printf(m, "speed:\t\t%d\n", speed);
7543 8125
7544 if (status & TP_EC_FAN_FULLSPEED) 8126 if (status & TP_EC_FAN_FULLSPEED)
7545 /* Disengaged mode takes precedence */ 8127 /* Disengaged mode takes precedence */
7546 len += sprintf(p + len, "level:\t\tdisengaged\n"); 8128 seq_printf(m, "level:\t\tdisengaged\n");
7547 else if (status & TP_EC_FAN_AUTO) 8129 else if (status & TP_EC_FAN_AUTO)
7548 len += sprintf(p + len, "level:\t\tauto\n"); 8130 seq_printf(m, "level:\t\tauto\n");
7549 else 8131 else
7550 len += sprintf(p + len, "level:\t\t%d\n", status); 8132 seq_printf(m, "level:\t\t%d\n", status);
7551 break; 8133 break;
7552 8134
7553 case TPACPI_FAN_NONE: 8135 case TPACPI_FAN_NONE:
7554 default: 8136 default:
7555 len += sprintf(p + len, "status:\t\tnot supported\n"); 8137 seq_printf(m, "status:\t\tnot supported\n");
7556 } 8138 }
7557 8139
7558 if (fan_control_commands & TPACPI_FAN_CMD_LEVEL) { 8140 if (fan_control_commands & TPACPI_FAN_CMD_LEVEL) {
7559 len += sprintf(p + len, "commands:\tlevel <level>"); 8141 seq_printf(m, "commands:\tlevel <level>");
7560 8142
7561 switch (fan_control_access_mode) { 8143 switch (fan_control_access_mode) {
7562 case TPACPI_FAN_WR_ACPI_SFAN: 8144 case TPACPI_FAN_WR_ACPI_SFAN:
7563 len += sprintf(p + len, " (<level> is 0-7)\n"); 8145 seq_printf(m, " (<level> is 0-7)\n");
7564 break; 8146 break;
7565 8147
7566 default: 8148 default:
7567 len += sprintf(p + len, " (<level> is 0-7, " 8149 seq_printf(m, " (<level> is 0-7, "
7568 "auto, disengaged, full-speed)\n"); 8150 "auto, disengaged, full-speed)\n");
7569 break; 8151 break;
7570 } 8152 }
7571 } 8153 }
7572 8154
7573 if (fan_control_commands & TPACPI_FAN_CMD_ENABLE) 8155 if (fan_control_commands & TPACPI_FAN_CMD_ENABLE)
7574 len += sprintf(p + len, "commands:\tenable, disable\n" 8156 seq_printf(m, "commands:\tenable, disable\n"
7575 "commands:\twatchdog <timeout> (<timeout> " 8157 "commands:\twatchdog <timeout> (<timeout> "
7576 "is 0 (off), 1-120 (seconds))\n"); 8158 "is 0 (off), 1-120 (seconds))\n");
7577 8159
7578 if (fan_control_commands & TPACPI_FAN_CMD_SPEED) 8160 if (fan_control_commands & TPACPI_FAN_CMD_SPEED)
7579 len += sprintf(p + len, "commands:\tspeed <speed>" 8161 seq_printf(m, "commands:\tspeed <speed>"
7580 " (<speed> is 0-65535)\n"); 8162 " (<speed> is 0-65535)\n");
7581 8163
7582 return len; 8164 return 0;
7583} 8165}
7584 8166
7585static int fan_write_cmd_level(const char *cmd, int *rc) 8167static int fan_write_cmd_level(const char *cmd, int *rc)
@@ -7721,10 +8303,23 @@ static struct ibm_struct fan_driver_data = {
7721 */ 8303 */
7722static void tpacpi_driver_event(const unsigned int hkey_event) 8304static void tpacpi_driver_event(const unsigned int hkey_event)
7723{ 8305{
8306 if (ibm_backlight_device) {
8307 switch (hkey_event) {
8308 case TP_HKEY_EV_BRGHT_UP:
8309 case TP_HKEY_EV_BRGHT_DOWN:
8310 tpacpi_brightness_notify_change();
8311 }
8312 }
8313 if (alsa_card) {
8314 switch (hkey_event) {
8315 case TP_HKEY_EV_VOL_UP:
8316 case TP_HKEY_EV_VOL_DOWN:
8317 case TP_HKEY_EV_VOL_MUTE:
8318 volume_alsa_notify_change();
8319 }
8320 }
7724} 8321}
7725 8322
7726
7727
7728static void hotkey_driver_event(const unsigned int scancode) 8323static void hotkey_driver_event(const unsigned int scancode)
7729{ 8324{
7730 tpacpi_driver_event(TP_HKEY_EV_HOTKEY_BASE + scancode); 8325 tpacpi_driver_event(TP_HKEY_EV_HOTKEY_BASE + scancode);
@@ -7853,19 +8448,19 @@ static int __init ibm_init(struct ibm_init_struct *iibm)
7853 "%s installed\n", ibm->name); 8448 "%s installed\n", ibm->name);
7854 8449
7855 if (ibm->read) { 8450 if (ibm->read) {
7856 entry = create_proc_entry(ibm->name, 8451 mode_t mode;
7857 S_IFREG | S_IRUGO | S_IWUSR, 8452
7858 proc_dir); 8453 mode = S_IRUGO;
8454 if (ibm->write)
8455 mode |= S_IWUSR;
8456 entry = proc_create_data(ibm->name, mode, proc_dir,
8457 &dispatch_proc_fops, ibm);
7859 if (!entry) { 8458 if (!entry) {
7860 printk(TPACPI_ERR "unable to create proc entry %s\n", 8459 printk(TPACPI_ERR "unable to create proc entry %s\n",
7861 ibm->name); 8460 ibm->name);
7862 ret = -ENODEV; 8461 ret = -ENODEV;
7863 goto err_out; 8462 goto err_out;
7864 } 8463 }
7865 entry->data = ibm;
7866 entry->read_proc = &dispatch_procfs_read;
7867 if (ibm->write)
7868 entry->write_proc = &dispatch_procfs_write;
7869 ibm->flags.proc_created = 1; 8464 ibm->flags.proc_created = 1;
7870 } 8465 }
7871 8466
@@ -8077,6 +8672,7 @@ static struct ibm_init_struct ibms_init[] __initdata = {
8077 .data = &brightness_driver_data, 8672 .data = &brightness_driver_data,
8078 }, 8673 },
8079 { 8674 {
8675 .init = volume_init,
8080 .data = &volume_driver_data, 8676 .data = &volume_driver_data,
8081 }, 8677 },
8082 { 8678 {
@@ -8112,36 +8708,59 @@ static int __init set_ibm_param(const char *val, struct kernel_param *kp)
8112 return -EINVAL; 8708 return -EINVAL;
8113} 8709}
8114 8710
8115module_param(experimental, int, 0); 8711module_param(experimental, int, 0444);
8116MODULE_PARM_DESC(experimental, 8712MODULE_PARM_DESC(experimental,
8117 "Enables experimental features when non-zero"); 8713 "Enables experimental features when non-zero");
8118 8714
8119module_param_named(debug, dbg_level, uint, 0); 8715module_param_named(debug, dbg_level, uint, 0);
8120MODULE_PARM_DESC(debug, "Sets debug level bit-mask"); 8716MODULE_PARM_DESC(debug, "Sets debug level bit-mask");
8121 8717
8122module_param(force_load, bool, 0); 8718module_param(force_load, bool, 0444);
8123MODULE_PARM_DESC(force_load, 8719MODULE_PARM_DESC(force_load,
8124 "Attempts to load the driver even on a " 8720 "Attempts to load the driver even on a "
8125 "mis-identified ThinkPad when true"); 8721 "mis-identified ThinkPad when true");
8126 8722
8127module_param_named(fan_control, fan_control_allowed, bool, 0); 8723module_param_named(fan_control, fan_control_allowed, bool, 0444);
8128MODULE_PARM_DESC(fan_control, 8724MODULE_PARM_DESC(fan_control,
8129 "Enables setting fan parameters features when true"); 8725 "Enables setting fan parameters features when true");
8130 8726
8131module_param_named(brightness_mode, brightness_mode, uint, 0); 8727module_param_named(brightness_mode, brightness_mode, uint, 0444);
8132MODULE_PARM_DESC(brightness_mode, 8728MODULE_PARM_DESC(brightness_mode,
8133 "Selects brightness control strategy: " 8729 "Selects brightness control strategy: "
8134 "0=auto, 1=EC, 2=UCMS, 3=EC+NVRAM"); 8730 "0=auto, 1=EC, 2=UCMS, 3=EC+NVRAM");
8135 8731
8136module_param(brightness_enable, uint, 0); 8732module_param(brightness_enable, uint, 0444);
8137MODULE_PARM_DESC(brightness_enable, 8733MODULE_PARM_DESC(brightness_enable,
8138 "Enables backlight control when 1, disables when 0"); 8734 "Enables backlight control when 1, disables when 0");
8139 8735
8140module_param(hotkey_report_mode, uint, 0); 8736module_param(hotkey_report_mode, uint, 0444);
8141MODULE_PARM_DESC(hotkey_report_mode, 8737MODULE_PARM_DESC(hotkey_report_mode,
8142 "used for backwards compatibility with userspace, " 8738 "used for backwards compatibility with userspace, "
8143 "see documentation"); 8739 "see documentation");
8144 8740
8741module_param_named(volume_mode, volume_mode, uint, 0444);
8742MODULE_PARM_DESC(volume_mode,
8743 "Selects volume control strategy: "
8744 "0=auto, 1=EC, 2=N/A, 3=EC+NVRAM");
8745
8746module_param_named(volume_capabilities, volume_capabilities, uint, 0444);
8747MODULE_PARM_DESC(volume_capabilities,
8748 "Selects the mixer capabilites: "
8749 "0=auto, 1=volume and mute, 2=mute only");
8750
8751module_param_named(volume_control, volume_control_allowed, bool, 0444);
8752MODULE_PARM_DESC(volume_control,
8753 "Enables software override for the console audio "
8754 "control when true");
8755
8756/* ALSA module API parameters */
8757module_param_named(index, alsa_index, int, 0444);
8758MODULE_PARM_DESC(index, "ALSA index for the ACPI EC Mixer");
8759module_param_named(id, alsa_id, charp, 0444);
8760MODULE_PARM_DESC(id, "ALSA id for the ACPI EC Mixer");
8761module_param_named(enable, alsa_enable, bool, 0444);
8762MODULE_PARM_DESC(enable, "Enable the ALSA interface for the ACPI EC Mixer");
8763
8145#define TPACPI_PARAM(feature) \ 8764#define TPACPI_PARAM(feature) \
8146 module_param_call(feature, set_ibm_param, NULL, NULL, 0); \ 8765 module_param_call(feature, set_ibm_param, NULL, NULL, 0); \
8147 MODULE_PARM_DESC(feature, "Simulates thinkpad-acpi procfs command " \ 8766 MODULE_PARM_DESC(feature, "Simulates thinkpad-acpi procfs command " \
@@ -8160,25 +8779,25 @@ TPACPI_PARAM(volume);
8160TPACPI_PARAM(fan); 8779TPACPI_PARAM(fan);
8161 8780
8162#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES 8781#ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES
8163module_param(dbg_wlswemul, uint, 0); 8782module_param(dbg_wlswemul, uint, 0444);
8164MODULE_PARM_DESC(dbg_wlswemul, "Enables WLSW emulation"); 8783MODULE_PARM_DESC(dbg_wlswemul, "Enables WLSW emulation");
8165module_param_named(wlsw_state, tpacpi_wlsw_emulstate, bool, 0); 8784module_param_named(wlsw_state, tpacpi_wlsw_emulstate, bool, 0);
8166MODULE_PARM_DESC(wlsw_state, 8785MODULE_PARM_DESC(wlsw_state,
8167 "Initial state of the emulated WLSW switch"); 8786 "Initial state of the emulated WLSW switch");
8168 8787
8169module_param(dbg_bluetoothemul, uint, 0); 8788module_param(dbg_bluetoothemul, uint, 0444);
8170MODULE_PARM_DESC(dbg_bluetoothemul, "Enables bluetooth switch emulation"); 8789MODULE_PARM_DESC(dbg_bluetoothemul, "Enables bluetooth switch emulation");
8171module_param_named(bluetooth_state, tpacpi_bluetooth_emulstate, bool, 0); 8790module_param_named(bluetooth_state, tpacpi_bluetooth_emulstate, bool, 0);
8172MODULE_PARM_DESC(bluetooth_state, 8791MODULE_PARM_DESC(bluetooth_state,
8173 "Initial state of the emulated bluetooth switch"); 8792 "Initial state of the emulated bluetooth switch");
8174 8793
8175module_param(dbg_wwanemul, uint, 0); 8794module_param(dbg_wwanemul, uint, 0444);
8176MODULE_PARM_DESC(dbg_wwanemul, "Enables WWAN switch emulation"); 8795MODULE_PARM_DESC(dbg_wwanemul, "Enables WWAN switch emulation");
8177module_param_named(wwan_state, tpacpi_wwan_emulstate, bool, 0); 8796module_param_named(wwan_state, tpacpi_wwan_emulstate, bool, 0);
8178MODULE_PARM_DESC(wwan_state, 8797MODULE_PARM_DESC(wwan_state,
8179 "Initial state of the emulated WWAN switch"); 8798 "Initial state of the emulated WWAN switch");
8180 8799
8181module_param(dbg_uwbemul, uint, 0); 8800module_param(dbg_uwbemul, uint, 0444);
8182MODULE_PARM_DESC(dbg_uwbemul, "Enables UWB switch emulation"); 8801MODULE_PARM_DESC(dbg_uwbemul, "Enables UWB switch emulation");
8183module_param_named(uwb_state, tpacpi_uwb_emulstate, bool, 0); 8802module_param_named(uwb_state, tpacpi_uwb_emulstate, bool, 0);
8184MODULE_PARM_DESC(uwb_state, 8803MODULE_PARM_DESC(uwb_state,
@@ -8371,6 +8990,7 @@ static int __init thinkpad_acpi_module_init(void)
8371 PCI_VENDOR_ID_IBM; 8990 PCI_VENDOR_ID_IBM;
8372 tpacpi_inputdev->id.product = TPACPI_HKEY_INPUT_PRODUCT; 8991 tpacpi_inputdev->id.product = TPACPI_HKEY_INPUT_PRODUCT;
8373 tpacpi_inputdev->id.version = TPACPI_HKEY_INPUT_VERSION; 8992 tpacpi_inputdev->id.version = TPACPI_HKEY_INPUT_VERSION;
8993 tpacpi_inputdev->dev.parent = &tpacpi_pdev->dev;
8374 } 8994 }
8375 for (i = 0; i < ARRAY_SIZE(ibms_init); i++) { 8995 for (i = 0; i < ARRAY_SIZE(ibms_init); i++) {
8376 ret = ibm_init(&ibms_init[i]); 8996 ret = ibm_init(&ibms_init[i]);
diff --git a/drivers/platform/x86/toshiba_bluetooth.c b/drivers/platform/x86/toshiba_bluetooth.c
new file mode 100644
index 000000000000..a350418e87ea
--- /dev/null
+++ b/drivers/platform/x86/toshiba_bluetooth.c
@@ -0,0 +1,144 @@
1/*
2 * Toshiba Bluetooth Enable Driver
3 *
4 * Copyright (C) 2009 Jes Sorensen <Jes.Sorensen@gmail.com>
5 *
6 * Thanks to Matthew Garrett for background info on ACPI innards which
7 * normal people aren't meant to understand :-)
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13 * Note the Toshiba Bluetooth RFKill switch seems to be a strange
14 * fish. It only provides a BT event when the switch is flipped to
15 * the 'on' position. When flipping it to 'off', the USB device is
16 * simply pulled away underneath us, without any BT event being
17 * delivered.
18 */
19
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/init.h>
23#include <linux/types.h>
24#include <acpi/acpi_bus.h>
25#include <acpi/acpi_drivers.h>
26
27MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@gmail.com>");
28MODULE_DESCRIPTION("Toshiba Laptop ACPI Bluetooth Enable Driver");
29MODULE_LICENSE("GPL");
30
31
32static int toshiba_bt_rfkill_add(struct acpi_device *device);
33static int toshiba_bt_rfkill_remove(struct acpi_device *device, int type);
34static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event);
35static int toshiba_bt_resume(struct acpi_device *device);
36
37static const struct acpi_device_id bt_device_ids[] = {
38 { "TOS6205", 0},
39 { "", 0},
40};
41MODULE_DEVICE_TABLE(acpi, bt_device_ids);
42
43static struct acpi_driver toshiba_bt_rfkill_driver = {
44 .name = "Toshiba BT",
45 .class = "Toshiba",
46 .ids = bt_device_ids,
47 .ops = {
48 .add = toshiba_bt_rfkill_add,
49 .remove = toshiba_bt_rfkill_remove,
50 .notify = toshiba_bt_rfkill_notify,
51 .resume = toshiba_bt_resume,
52 },
53 .owner = THIS_MODULE,
54};
55
56
57static int toshiba_bluetooth_enable(acpi_handle handle)
58{
59 acpi_status res1, res2;
60 acpi_integer result;
61
62 /*
63 * Query ACPI to verify RFKill switch is set to 'on'.
64 * If not, we return silently, no need to report it as
65 * an error.
66 */
67 res1 = acpi_evaluate_integer(handle, "BTST", NULL, &result);
68 if (ACPI_FAILURE(res1))
69 return res1;
70 if (!(result & 0x01))
71 return 0;
72
73 printk(KERN_INFO "toshiba_bluetooth: Re-enabling Toshiba Bluetooth\n");
74 res1 = acpi_evaluate_object(handle, "AUSB", NULL, NULL);
75 res2 = acpi_evaluate_object(handle, "BTPO", NULL, NULL);
76 if (!ACPI_FAILURE(res1) || !ACPI_FAILURE(res2))
77 return 0;
78
79 printk(KERN_WARNING "toshiba_bluetooth: Failed to re-enable "
80 "Toshiba Bluetooth\n");
81
82 return -ENODEV;
83}
84
85static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event)
86{
87 toshiba_bluetooth_enable(device->handle);
88}
89
90static int toshiba_bt_resume(struct acpi_device *device)
91{
92 return toshiba_bluetooth_enable(device->handle);
93}
94
95static int toshiba_bt_rfkill_add(struct acpi_device *device)
96{
97 acpi_status status;
98 acpi_integer bt_present;
99 int result = -ENODEV;
100
101 /*
102 * Some Toshiba laptops may have a fake TOS6205 device in
103 * their ACPI BIOS, so query the _STA method to see if there
104 * is really anything there, before trying to enable it.
105 */
106 status = acpi_evaluate_integer(device->handle, "_STA", NULL,
107 &bt_present);
108
109 if (!ACPI_FAILURE(status) && bt_present) {
110 printk(KERN_INFO "Detected Toshiba ACPI Bluetooth device - "
111 "installing RFKill handler\n");
112 result = toshiba_bluetooth_enable(device->handle);
113 }
114
115 return result;
116}
117
118static int __init toshiba_bt_rfkill_init(void)
119{
120 int result;
121
122 result = acpi_bus_register_driver(&toshiba_bt_rfkill_driver);
123 if (result < 0) {
124 ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
125 "Error registering driver\n"));
126 return result;
127 }
128
129 return 0;
130}
131
132static int toshiba_bt_rfkill_remove(struct acpi_device *device, int type)
133{
134 /* clean up */
135 return 0;
136}
137
138static void __exit toshiba_bt_rfkill_exit(void)
139{
140 acpi_bus_unregister_driver(&toshiba_bt_rfkill_driver);
141}
142
143module_init(toshiba_bt_rfkill_init);
144module_exit(toshiba_bt_rfkill_exit);
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
index 177f8d767df4..e425a868cd3a 100644
--- a/drivers/platform/x86/wmi.c
+++ b/drivers/platform/x86/wmi.c
@@ -30,6 +30,7 @@
30#include <linux/kernel.h> 30#include <linux/kernel.h>
31#include <linux/init.h> 31#include <linux/init.h>
32#include <linux/types.h> 32#include <linux/types.h>
33#include <linux/device.h>
33#include <linux/list.h> 34#include <linux/list.h>
34#include <linux/acpi.h> 35#include <linux/acpi.h>
35#include <acpi/acpi_bus.h> 36#include <acpi/acpi_bus.h>
@@ -65,6 +66,7 @@ struct wmi_block {
65 acpi_handle handle; 66 acpi_handle handle;
66 wmi_notify_handler handler; 67 wmi_notify_handler handler;
67 void *handler_data; 68 void *handler_data;
69 struct device *dev;
68}; 70};
69 71
70static struct wmi_block wmi_blocks; 72static struct wmi_block wmi_blocks;
@@ -195,6 +197,34 @@ static bool wmi_parse_guid(const u8 *src, u8 *dest)
195 return true; 197 return true;
196} 198}
197 199
200/*
201 * Convert a raw GUID to the ACII string representation
202 */
203static int wmi_gtoa(const char *in, char *out)
204{
205 int i;
206
207 for (i = 3; i >= 0; i--)
208 out += sprintf(out, "%02X", in[i] & 0xFF);
209
210 out += sprintf(out, "-");
211 out += sprintf(out, "%02X", in[5] & 0xFF);
212 out += sprintf(out, "%02X", in[4] & 0xFF);
213 out += sprintf(out, "-");
214 out += sprintf(out, "%02X", in[7] & 0xFF);
215 out += sprintf(out, "%02X", in[6] & 0xFF);
216 out += sprintf(out, "-");
217 out += sprintf(out, "%02X", in[8] & 0xFF);
218 out += sprintf(out, "%02X", in[9] & 0xFF);
219 out += sprintf(out, "-");
220
221 for (i = 10; i <= 15; i++)
222 out += sprintf(out, "%02X", in[i] & 0xFF);
223
224 out = '\0';
225 return 0;
226}
227
198static bool find_guid(const char *guid_string, struct wmi_block **out) 228static bool find_guid(const char *guid_string, struct wmi_block **out)
199{ 229{
200 char tmp[16], guid_input[16]; 230 char tmp[16], guid_input[16];
@@ -555,6 +585,138 @@ bool wmi_has_guid(const char *guid_string)
555EXPORT_SYMBOL_GPL(wmi_has_guid); 585EXPORT_SYMBOL_GPL(wmi_has_guid);
556 586
557/* 587/*
588 * sysfs interface
589 */
590static ssize_t show_modalias(struct device *dev, struct device_attribute *attr,
591 char *buf)
592{
593 char guid_string[37];
594 struct wmi_block *wblock;
595
596 wblock = dev_get_drvdata(dev);
597 if (!wblock)
598 return -ENOMEM;
599
600 wmi_gtoa(wblock->gblock.guid, guid_string);
601
602 return sprintf(buf, "wmi:%s\n", guid_string);
603}
604static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
605
606static int wmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
607{
608 char guid_string[37];
609
610 struct wmi_block *wblock;
611
612 if (add_uevent_var(env, "MODALIAS="))
613 return -ENOMEM;
614
615 wblock = dev_get_drvdata(dev);
616 if (!wblock)
617 return -ENOMEM;
618
619 wmi_gtoa(wblock->gblock.guid, guid_string);
620
621 strcpy(&env->buf[env->buflen - 1], "wmi:");
622 memcpy(&env->buf[env->buflen - 1 + 4], guid_string, 36);
623 env->buflen += 40;
624
625 return 0;
626}
627
628static void wmi_dev_free(struct device *dev)
629{
630 kfree(dev);
631}
632
633static struct class wmi_class = {
634 .name = "wmi",
635 .dev_release = wmi_dev_free,
636 .dev_uevent = wmi_dev_uevent,
637};
638
639static int wmi_create_devs(void)
640{
641 int result;
642 char guid_string[37];
643 struct guid_block *gblock;
644 struct wmi_block *wblock;
645 struct list_head *p;
646 struct device *guid_dev;
647
648 /* Create devices for all the GUIDs */
649 list_for_each(p, &wmi_blocks.list) {
650 wblock = list_entry(p, struct wmi_block, list);
651
652 guid_dev = kzalloc(sizeof(struct device), GFP_KERNEL);
653 if (!guid_dev)
654 return -ENOMEM;
655
656 wblock->dev = guid_dev;
657
658 guid_dev->class = &wmi_class;
659 dev_set_drvdata(guid_dev, wblock);
660
661 gblock = &wblock->gblock;
662
663 wmi_gtoa(gblock->guid, guid_string);
664 dev_set_name(guid_dev, guid_string);
665
666 result = device_register(guid_dev);
667 if (result)
668 return result;
669
670 result = device_create_file(guid_dev, &dev_attr_modalias);
671 if (result)
672 return result;
673 }
674
675 return 0;
676}
677
678static void wmi_remove_devs(void)
679{
680 struct guid_block *gblock;
681 struct wmi_block *wblock;
682 struct list_head *p;
683 struct device *guid_dev;
684
685 /* Delete devices for all the GUIDs */
686 list_for_each(p, &wmi_blocks.list) {
687 wblock = list_entry(p, struct wmi_block, list);
688
689 guid_dev = wblock->dev;
690 gblock = &wblock->gblock;
691
692 device_remove_file(guid_dev, &dev_attr_modalias);
693
694 device_unregister(guid_dev);
695 }
696}
697
698static void wmi_class_exit(void)
699{
700 wmi_remove_devs();
701 class_unregister(&wmi_class);
702}
703
704static int wmi_class_init(void)
705{
706 int ret;
707
708 ret = class_register(&wmi_class);
709 if (ret)
710 return ret;
711
712 ret = wmi_create_devs();
713 if (ret)
714 wmi_class_exit();
715
716 return ret;
717}
718
719/*
558 * Parse the _WDG method for the GUID data blocks 720 * Parse the _WDG method for the GUID data blocks
559 */ 721 */
560static __init acpi_status parse_wdg(acpi_handle handle) 722static __init acpi_status parse_wdg(acpi_handle handle)
@@ -709,10 +871,17 @@ static int __init acpi_wmi_init(void)
709 871
710 if (result < 0) { 872 if (result < 0) {
711 printk(KERN_INFO PREFIX "Error loading mapper\n"); 873 printk(KERN_INFO PREFIX "Error loading mapper\n");
712 } else { 874 return -ENODEV;
713 printk(KERN_INFO PREFIX "Mapper loaded\n"); 875 }
876
877 result = wmi_class_init();
878 if (result) {
879 acpi_bus_unregister_driver(&acpi_wmi_driver);
880 return result;
714 } 881 }
715 882
883 printk(KERN_INFO PREFIX "Mapper loaded\n");
884
716 return result; 885 return result;
717} 886}
718 887
@@ -721,6 +890,8 @@ static void __exit acpi_wmi_exit(void)
721 struct list_head *p, *tmp; 890 struct list_head *p, *tmp;
722 struct wmi_block *wblock; 891 struct wmi_block *wblock;
723 892
893 wmi_class_exit();
894
724 acpi_bus_unregister_driver(&acpi_wmi_driver); 895 acpi_bus_unregister_driver(&acpi_wmi_driver);
725 896
726 list_for_each_safe(p, tmp, &wmi_blocks.list) { 897 list_for_each_safe(p, tmp, &wmi_blocks.list) {
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index 83b8b5ac49c9..5314bf630bc4 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -80,7 +80,8 @@ static int pnpacpi_get_resources(struct pnp_dev *dev)
80 80
81static int pnpacpi_set_resources(struct pnp_dev *dev) 81static int pnpacpi_set_resources(struct pnp_dev *dev)
82{ 82{
83 acpi_handle handle = dev->data; 83 struct acpi_device *acpi_dev = dev->data;
84 acpi_handle handle = acpi_dev->handle;
84 struct acpi_buffer buffer; 85 struct acpi_buffer buffer;
85 int ret; 86 int ret;
86 87
@@ -103,7 +104,8 @@ static int pnpacpi_set_resources(struct pnp_dev *dev)
103 104
104static int pnpacpi_disable_resources(struct pnp_dev *dev) 105static int pnpacpi_disable_resources(struct pnp_dev *dev)
105{ 106{
106 acpi_handle handle = dev->data; 107 struct acpi_device *acpi_dev = dev->data;
108 acpi_handle handle = acpi_dev->handle;
107 int ret; 109 int ret;
108 110
109 dev_dbg(&dev->dev, "disable resources\n"); 111 dev_dbg(&dev->dev, "disable resources\n");
@@ -121,6 +123,8 @@ static int pnpacpi_disable_resources(struct pnp_dev *dev)
121#ifdef CONFIG_ACPI_SLEEP 123#ifdef CONFIG_ACPI_SLEEP
122static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state) 124static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state)
123{ 125{
126 struct acpi_device *acpi_dev = dev->data;
127 acpi_handle handle = acpi_dev->handle;
124 int power_state; 128 int power_state;
125 129
126 power_state = acpi_pm_device_sleep_state(&dev->dev, NULL); 130 power_state = acpi_pm_device_sleep_state(&dev->dev, NULL);
@@ -128,16 +132,19 @@ static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state)
128 power_state = (state.event == PM_EVENT_ON) ? 132 power_state = (state.event == PM_EVENT_ON) ?
129 ACPI_STATE_D0 : ACPI_STATE_D3; 133 ACPI_STATE_D0 : ACPI_STATE_D3;
130 134
131 return acpi_bus_set_power((acpi_handle) dev->data, power_state); 135 return acpi_bus_set_power(handle, power_state);
132} 136}
133 137
134static int pnpacpi_resume(struct pnp_dev *dev) 138static int pnpacpi_resume(struct pnp_dev *dev)
135{ 139{
136 return acpi_bus_set_power((acpi_handle) dev->data, ACPI_STATE_D0); 140 struct acpi_device *acpi_dev = dev->data;
141 acpi_handle handle = acpi_dev->handle;
142
143 return acpi_bus_set_power(handle, ACPI_STATE_D0);
137} 144}
138#endif 145#endif
139 146
140static struct pnp_protocol pnpacpi_protocol = { 147struct pnp_protocol pnpacpi_protocol = {
141 .name = "Plug and Play ACPI", 148 .name = "Plug and Play ACPI",
142 .get = pnpacpi_get_resources, 149 .get = pnpacpi_get_resources,
143 .set = pnpacpi_set_resources, 150 .set = pnpacpi_set_resources,
@@ -147,6 +154,7 @@ static struct pnp_protocol pnpacpi_protocol = {
147 .resume = pnpacpi_resume, 154 .resume = pnpacpi_resume,
148#endif 155#endif
149}; 156};
157EXPORT_SYMBOL(pnpacpi_protocol);
150 158
151static int __init pnpacpi_add_device(struct acpi_device *device) 159static int __init pnpacpi_add_device(struct acpi_device *device)
152{ 160{
@@ -168,7 +176,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
168 if (!dev) 176 if (!dev)
169 return -ENOMEM; 177 return -ENOMEM;
170 178
171 dev->data = device->handle; 179 dev->data = device;
172 /* .enabled means the device can decode the resources */ 180 /* .enabled means the device can decode the resources */
173 dev->active = device->status.enabled; 181 dev->active = device->status.enabled;
174 status = acpi_get_handle(device->handle, "_SRS", &temp); 182 status = acpi_get_handle(device->handle, "_SRS", &temp);
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index ef3a2cd3a7a0..5702b2c8691f 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -465,7 +465,8 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
465 465
466int pnpacpi_parse_allocated_resource(struct pnp_dev *dev) 466int pnpacpi_parse_allocated_resource(struct pnp_dev *dev)
467{ 467{
468 acpi_handle handle = dev->data; 468 struct acpi_device *acpi_dev = dev->data;
469 acpi_handle handle = acpi_dev->handle;
469 acpi_status status; 470 acpi_status status;
470 471
471 pnp_dbg(&dev->dev, "parse allocated resources\n"); 472 pnp_dbg(&dev->dev, "parse allocated resources\n");
@@ -773,7 +774,8 @@ static __init acpi_status pnpacpi_option_resource(struct acpi_resource *res,
773 774
774int __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev) 775int __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev)
775{ 776{
776 acpi_handle handle = dev->data; 777 struct acpi_device *acpi_dev = dev->data;
778 acpi_handle handle = acpi_dev->handle;
777 acpi_status status; 779 acpi_status status;
778 struct acpipnp_parse_option_s parse_data; 780 struct acpipnp_parse_option_s parse_data;
779 781
@@ -845,7 +847,8 @@ static acpi_status pnpacpi_type_resources(struct acpi_resource *res, void *data)
845int pnpacpi_build_resource_template(struct pnp_dev *dev, 847int pnpacpi_build_resource_template(struct pnp_dev *dev,
846 struct acpi_buffer *buffer) 848 struct acpi_buffer *buffer)
847{ 849{
848 acpi_handle handle = dev->data; 850 struct acpi_device *acpi_dev = dev->data;
851 acpi_handle handle = acpi_dev->handle;
849 struct acpi_resource *resource; 852 struct acpi_resource *resource;
850 int res_cnt = 0; 853 int res_cnt = 0;
851 acpi_status status; 854 acpi_status status;
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c
index 6f8d8f971212..5066de5cfc0c 100644
--- a/drivers/thermal/thermal_sys.c
+++ b/drivers/thermal/thermal_sys.c
@@ -225,6 +225,12 @@ passive_store(struct device *dev, struct device_attribute *attr,
225 if (!sscanf(buf, "%d\n", &state)) 225 if (!sscanf(buf, "%d\n", &state))
226 return -EINVAL; 226 return -EINVAL;
227 227
228 /* sanity check: values below 1000 millicelcius don't make sense
229 * and can cause the system to go into a thermal heart attack
230 */
231 if (state && state < 1000)
232 return -EINVAL;
233
228 if (state && !tz->forced_passive) { 234 if (state && !tz->forced_passive) {
229 mutex_lock(&thermal_list_lock); 235 mutex_lock(&thermal_list_lock);
230 list_for_each_entry(cdev, &thermal_cdev_list, node) { 236 list_for_each_entry(cdev, &thermal_cdev_list, node) {
@@ -235,6 +241,8 @@ passive_store(struct device *dev, struct device_attribute *attr,
235 cdev); 241 cdev);
236 } 242 }
237 mutex_unlock(&thermal_list_lock); 243 mutex_unlock(&thermal_list_lock);
244 if (!tz->passive_delay)
245 tz->passive_delay = 1000;
238 } else if (!state && tz->forced_passive) { 246 } else if (!state && tz->forced_passive) {
239 mutex_lock(&thermal_list_lock); 247 mutex_lock(&thermal_list_lock);
240 list_for_each_entry(cdev, &thermal_cdev_list, node) { 248 list_for_each_entry(cdev, &thermal_cdev_list, node) {
@@ -245,17 +253,12 @@ passive_store(struct device *dev, struct device_attribute *attr,
245 cdev); 253 cdev);
246 } 254 }
247 mutex_unlock(&thermal_list_lock); 255 mutex_unlock(&thermal_list_lock);
256 tz->passive_delay = 0;
248 } 257 }
249 258
250 tz->tc1 = 1; 259 tz->tc1 = 1;
251 tz->tc2 = 1; 260 tz->tc2 = 1;
252 261
253 if (!tz->passive_delay)
254 tz->passive_delay = 1000;
255
256 if (!tz->polling_delay)
257 tz->polling_delay = 10000;
258
259 tz->forced_passive = state; 262 tz->forced_passive = state;
260 263
261 thermal_zone_device_update(tz); 264 thermal_zone_device_update(tz);
@@ -374,7 +377,7 @@ thermal_cooling_device_cur_state_store(struct device *dev,
374 if (!sscanf(buf, "%ld\n", &state)) 377 if (!sscanf(buf, "%ld\n", &state))
375 return -EINVAL; 378 return -EINVAL;
376 379
377 if (state < 0) 380 if ((long)state < 0)
378 return -EINVAL; 381 return -EINVAL;
379 382
380 result = cdev->ops->set_cur_state(cdev, state); 383 result = cdev->ops->set_cur_state(cdev, state);
@@ -1016,6 +1019,8 @@ void thermal_zone_device_update(struct thermal_zone_device *tz)
1016 thermal_zone_device_set_polling(tz, tz->passive_delay); 1019 thermal_zone_device_set_polling(tz, tz->passive_delay);
1017 else if (tz->polling_delay) 1020 else if (tz->polling_delay)
1018 thermal_zone_device_set_polling(tz, tz->polling_delay); 1021 thermal_zone_device_set_polling(tz, tz->polling_delay);
1022 else
1023 thermal_zone_device_set_polling(tz, 0);
1019 mutex_unlock(&tz->lock); 1024 mutex_unlock(&tz->lock);
1020} 1025}
1021EXPORT_SYMBOL(thermal_zone_device_update); 1026EXPORT_SYMBOL(thermal_zone_device_update);
diff --git a/include/acpi/acoutput.h b/include/acpi/acoutput.h
index 5c823d5ab783..d814da4b5365 100644
--- a/include/acpi/acoutput.h
+++ b/include/acpi/acoutput.h
@@ -85,7 +85,8 @@
85#define ACPI_LV_INIT 0x00000001 85#define ACPI_LV_INIT 0x00000001
86#define ACPI_LV_DEBUG_OBJECT 0x00000002 86#define ACPI_LV_DEBUG_OBJECT 0x00000002
87#define ACPI_LV_INFO 0x00000004 87#define ACPI_LV_INFO 0x00000004
88#define ACPI_LV_ALL_EXCEPTIONS 0x00000007 88#define ACPI_LV_REPAIR 0x00000008
89#define ACPI_LV_ALL_EXCEPTIONS 0x0000000F
89 90
90/* Trace verbosity level 1 [Standard Trace Level] */ 91/* Trace verbosity level 1 [Standard Trace Level] */
91 92
@@ -143,6 +144,7 @@
143#define ACPI_DB_INIT ACPI_DEBUG_LEVEL (ACPI_LV_INIT) 144#define ACPI_DB_INIT ACPI_DEBUG_LEVEL (ACPI_LV_INIT)
144#define ACPI_DB_DEBUG_OBJECT ACPI_DEBUG_LEVEL (ACPI_LV_DEBUG_OBJECT) 145#define ACPI_DB_DEBUG_OBJECT ACPI_DEBUG_LEVEL (ACPI_LV_DEBUG_OBJECT)
145#define ACPI_DB_INFO ACPI_DEBUG_LEVEL (ACPI_LV_INFO) 146#define ACPI_DB_INFO ACPI_DEBUG_LEVEL (ACPI_LV_INFO)
147#define ACPI_DB_REPAIR ACPI_DEBUG_LEVEL (ACPI_LV_REPAIR)
146#define ACPI_DB_ALL_EXCEPTIONS ACPI_DEBUG_LEVEL (ACPI_LV_ALL_EXCEPTIONS) 148#define ACPI_DB_ALL_EXCEPTIONS ACPI_DEBUG_LEVEL (ACPI_LV_ALL_EXCEPTIONS)
147 149
148/* Trace level -- also used in the global "DebugLevel" */ 150/* Trace level -- also used in the global "DebugLevel" */
@@ -174,8 +176,8 @@
174 176
175/* Defaults for debug_level, debug and normal */ 177/* Defaults for debug_level, debug and normal */
176 178
177#define ACPI_DEBUG_DEFAULT (ACPI_LV_INFO) 179#define ACPI_DEBUG_DEFAULT (ACPI_LV_INFO | ACPI_LV_REPAIR)
178#define ACPI_NORMAL_DEFAULT (ACPI_LV_INIT | ACPI_LV_DEBUG_OBJECT) 180#define ACPI_NORMAL_DEFAULT (ACPI_LV_INIT | ACPI_LV_DEBUG_OBJECT | ACPI_LV_REPAIR)
179#define ACPI_DEBUG_ALL (ACPI_LV_AML_DISASSEMBLE | ACPI_LV_ALL_EXCEPTIONS | ACPI_LV_ALL) 181#define ACPI_DEBUG_ALL (ACPI_LV_AML_DISASSEMBLE | ACPI_LV_ALL_EXCEPTIONS | ACPI_LV_ALL)
180 182
181#if defined (ACPI_DEBUG_OUTPUT) || !defined (ACPI_NO_ERROR_MESSAGES) 183#if defined (ACPI_DEBUG_OUTPUT) || !defined (ACPI_NO_ERROR_MESSAGES)
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index 5e1ad3cd1bbd..86e9735a96bd 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -47,7 +47,7 @@
47 47
48/* Current ACPICA subsystem version in YYYYMMDD format */ 48/* Current ACPICA subsystem version in YYYYMMDD format */
49 49
50#define ACPI_CA_VERSION 0x20091112 50#define ACPI_CA_VERSION 0x20091214
51 51
52#include "actypes.h" 52#include "actypes.h"
53#include "actbl.h" 53#include "actbl.h"
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index 8b668ead6d6e..29245c6b5c0e 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -294,7 +294,7 @@ static inline void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx
294#ifdef CONFIG_CPU_FREQ 294#ifdef CONFIG_CPU_FREQ
295void acpi_processor_ppc_init(void); 295void acpi_processor_ppc_init(void);
296void acpi_processor_ppc_exit(void); 296void acpi_processor_ppc_exit(void);
297int acpi_processor_ppc_has_changed(struct acpi_processor *pr); 297int acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag);
298extern int acpi_processor_get_bios_limit(int cpu, unsigned int *limit); 298extern int acpi_processor_get_bios_limit(int cpu, unsigned int *limit);
299#else 299#else
300static inline void acpi_processor_ppc_init(void) 300static inline void acpi_processor_ppc_init(void)
@@ -305,7 +305,8 @@ static inline void acpi_processor_ppc_exit(void)
305{ 305{
306 return; 306 return;
307} 307}
308static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr) 308static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr,
309 int event_flag)
309{ 310{
310 static unsigned int printout = 1; 311 static unsigned int printout = 1;
311 if (printout) { 312 if (printout) {
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index dfcd920c3e54..ce945d4845fc 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -240,7 +240,7 @@ extern int pnpacpi_disabled;
240#define PXM_INVAL (-1) 240#define PXM_INVAL (-1)
241#define NID_INVAL (-1) 241#define NID_INVAL (-1)
242 242
243int acpi_check_resource_conflict(struct resource *res); 243int acpi_check_resource_conflict(const struct resource *res);
244 244
245int acpi_check_region(resource_size_t start, resource_size_t n, 245int acpi_check_region(resource_size_t start, resource_size_t n,
246 const char *name); 246 const char *name);
@@ -253,10 +253,16 @@ void __init acpi_old_suspend_ordering(void);
253void __init acpi_s4_no_nvs(void); 253void __init acpi_s4_no_nvs(void);
254#endif /* CONFIG_PM_SLEEP */ 254#endif /* CONFIG_PM_SLEEP */
255 255
256struct acpi_osc_context {
257 char *uuid_str; /* uuid string */
258 int rev;
259 struct acpi_buffer cap; /* arg2/arg3 */
260 struct acpi_buffer ret; /* free by caller if success */
261};
262
256#define OSC_QUERY_TYPE 0 263#define OSC_QUERY_TYPE 0
257#define OSC_SUPPORT_TYPE 1 264#define OSC_SUPPORT_TYPE 1
258#define OSC_CONTROL_TYPE 2 265#define OSC_CONTROL_TYPE 2
259#define OSC_SUPPORT_MASKS 0x1f
260 266
261/* _OSC DW0 Definition */ 267/* _OSC DW0 Definition */
262#define OSC_QUERY_ENABLE 1 268#define OSC_QUERY_ENABLE 1
@@ -265,12 +271,23 @@ void __init acpi_s4_no_nvs(void);
265#define OSC_INVALID_REVISION_ERROR 8 271#define OSC_INVALID_REVISION_ERROR 8
266#define OSC_CAPABILITIES_MASK_ERROR 16 272#define OSC_CAPABILITIES_MASK_ERROR 16
267 273
274acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context);
275
276/* platform-wide _OSC bits */
277#define OSC_SB_PAD_SUPPORT 1
278#define OSC_SB_PPC_OST_SUPPORT 2
279#define OSC_SB_PR3_SUPPORT 4
280#define OSC_SB_CPUHP_OST_SUPPORT 8
281#define OSC_SB_APEI_SUPPORT 16
282
283/* PCI defined _OSC bits */
268/* _OSC DW1 Definition (OS Support Fields) */ 284/* _OSC DW1 Definition (OS Support Fields) */
269#define OSC_EXT_PCI_CONFIG_SUPPORT 1 285#define OSC_EXT_PCI_CONFIG_SUPPORT 1
270#define OSC_ACTIVE_STATE_PWR_SUPPORT 2 286#define OSC_ACTIVE_STATE_PWR_SUPPORT 2
271#define OSC_CLOCK_PWR_CAPABILITY_SUPPORT 4 287#define OSC_CLOCK_PWR_CAPABILITY_SUPPORT 4
272#define OSC_PCI_SEGMENT_GROUPS_SUPPORT 8 288#define OSC_PCI_SEGMENT_GROUPS_SUPPORT 8
273#define OSC_MSI_SUPPORT 16 289#define OSC_MSI_SUPPORT 16
290#define OSC_PCI_SUPPORT_MASKS 0x1f
274 291
275/* _OSC DW1 Definition (OS Control Fields) */ 292/* _OSC DW1 Definition (OS Control Fields) */
276#define OSC_PCI_EXPRESS_NATIVE_HP_CONTROL 1 293#define OSC_PCI_EXPRESS_NATIVE_HP_CONTROL 1
@@ -279,7 +296,7 @@ void __init acpi_s4_no_nvs(void);
279#define OSC_PCI_EXPRESS_AER_CONTROL 8 296#define OSC_PCI_EXPRESS_AER_CONTROL 8
280#define OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL 16 297#define OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL 16
281 298
282#define OSC_CONTROL_MASKS (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | \ 299#define OSC_PCI_CONTROL_MASKS (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | \
283 OSC_SHPC_NATIVE_HP_CONTROL | \ 300 OSC_SHPC_NATIVE_HP_CONTROL | \
284 OSC_PCI_EXPRESS_PME_CONTROL | \ 301 OSC_PCI_EXPRESS_PME_CONTROL | \
285 OSC_PCI_EXPRESS_AER_CONTROL | \ 302 OSC_PCI_EXPRESS_AER_CONTROL | \
diff --git a/include/linux/pnp.h b/include/linux/pnp.h
index fddfafaed024..7c4193eb0072 100644
--- a/include/linux/pnp.h
+++ b/include/linux/pnp.h
@@ -334,6 +334,19 @@ extern struct pnp_protocol pnpbios_protocol;
334#define pnp_device_is_pnpbios(dev) 0 334#define pnp_device_is_pnpbios(dev) 0
335#endif 335#endif
336 336
337#ifdef CONFIG_PNPACPI
338extern struct pnp_protocol pnpacpi_protocol;
339
340static inline struct acpi_device *pnp_acpi_device(struct pnp_dev *dev)
341{
342 if (dev->protocol == &pnpacpi_protocol)
343 return dev->data;
344 return NULL;
345}
346#else
347#define pnp_acpi_device(dev) 0
348#endif
349
337/* status */ 350/* status */
338#define PNP_READY 0x0000 351#define PNP_READY 0x0000
339#define PNP_ATTACHED 0x0001 352#define PNP_ATTACHED 0x0001