Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6

* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: (117 commits)
ACPI processor: Fix section mismatch for processor_add()
ACPI: Add platform-wide _OSC support.
ACPI: cleanup pci_root _OSC code.
ACPI: Add a generic API for _OSC -v2
msi-wmi: depend on backlight and fix corner-cases problems
msi-wmi: switch to using input sparse keymap library
msi-wmi: replace one-condition switch-case with if statement
msi-wmi: remove unused field 'instance' in key_entry structure
msi-wmi: remove custom runtime debug implementation
msi-wmi: rework init
msi-wmi: remove useless includes
X86 drivers: Introduce msi-wmi driver
Toshiba Bluetooth Enabling driver (RFKill handler v3)
ACPI: fix for lapic_timer_propagate_broadcast()
acpi_pad: squish warning
ACPI: dock: minor whitespace and style cleanups
ACPI: dock: add struct dock_station * directly to platform device data
ACPI: dock: dock_add - hoist up platform_device_register_simple()
ACPI: dock: remove global 'dock_device_name'
ACPI: dock: combine add|alloc_dock_dependent_device (v2)
...

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