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 474 Who: Jean Delvare <khali@linux-fr.org> 475 475 476 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 1 ThinkPad ACPI Extras Driver 2 2 3 - Version 0.23 4 - April 10th, 2009 3 + Version 0.24 4 + December 11th, 2009 5 5 6 6 Borislav Deianov <borislav@users.sf.net> 7 7 Henrique de Moraes Holschuh <hmh@hmh.eng.br> ··· 460 460 For Lenovo ThinkPads with a new 461 461 BIOS, it has to be handled either 462 462 by the ACPI OSI, or by userspace. 463 + The driver does the right thing, 464 + never mess with this. 463 465 0x1011 0x10 FN+END Brightness down. See brightness 464 466 up for details. 465 467 ··· 584 582 585 583 Brightness hotkey notes: 586 584 587 - These are the current sane choices for brightness key mapping in 588 - thinkpad-acpi: 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. 589 587 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. 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. 627 594 628 595 629 596 Bluetooth ··· 1092 1121 its level up and down at every change. 1093 1122 1094 1123 1095 - Volume control -- /proc/acpi/ibm/volume 1096 - --------------------------------------- 1124 + Volume control 1125 + -------------- 1097 1126 1098 - This feature allows volume control on ThinkPad models which don't have 1099 - a hardware volume knob. The available commands are: 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: 1100 1145 1101 1146 echo up >/proc/acpi/ibm/volume 1102 1147 echo down >/proc/acpi/ibm/volume 1103 1148 echo mute >/proc/acpi/ibm/volume 1149 + echo unmute >/proc/acpi/ibm/volume 1104 1150 echo 'level <level>' >/proc/acpi/ibm/volume 1105 1151 1106 - The <level> number range is 0 to 15 although not all of them may be 1152 + The <level> number range is 0 to 14 although not all of them may be 1107 1153 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). 1154 + up or down command (the level command will not unmute the volume), or 1155 + the unmute command. 1156 + 1109 1157 The current volume level and mute state is shown in the file. 1110 1158 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. 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. 1114 1179 1115 1180 1116 1181 Fan control and monitoring: fan speed, fan enable/disable ··· 1412 1405 0x0008 HKEY event interface, hotkeys 1413 1406 0x0010 Fan control 1414 1407 0x0020 Backlight brightness 1408 + 0x0040 Audio mixer/volume control 1415 1409 1416 1410 There is also a kernel build option to enable more debugging 1417 1411 information, which may be necessary to debug driver problems. ··· 1473 1465 and it is always able to disable hot keys. Very old 1474 1466 thinkpads are properly supported. hotkey_bios_mask 1475 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 206 passive trip point for the zone. Activation is done by polling with 207 207 an interval of 1 second. 208 208 Unit: millidegrees Celsius 209 + Valid values: 0 (disabled) or greater than 1000 209 210 RW, Optional 210 211 211 212 *****************************
+1 -1
arch/x86/kernel/acpi/cstate.c
··· 48 48 * P4, Core and beyond CPUs 49 49 */ 50 50 if (c->x86_vendor == X86_VENDOR_INTEL && 51 - (c->x86 > 0xf || (c->x86 == 6 && c->x86_model >= 14))) 51 + (c->x86 > 0xf || (c->x86 == 6 && c->x86_model >= 0x0f))) 52 52 flags->bm_control = 0; 53 53 } 54 54 EXPORT_SYMBOL(acpi_processor_power_init_bm_check);
+2 -1
drivers/acpi/acpi_pad.c
··· 100 100 struct cpumask *pad_busy_cpus = to_cpumask(pad_busy_cpus_bits); 101 101 cpumask_var_t tmp; 102 102 int cpu; 103 - unsigned long min_weight = -1, preferred_cpu; 103 + unsigned long min_weight = -1; 104 + unsigned long uninitialized_var(preferred_cpu); 104 105 105 106 if (!alloc_cpumask_var(&tmp, GFP_KERNEL)) 106 107 return;
+6 -3
drivers/acpi/acpica/acnamesp.h
··· 296 296 acpi_status validate_status, 297 297 union acpi_operand_object **return_object_ptr); 298 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 + 299 304 /* 300 305 * nssearch - Namespace searching and entry 301 306 */ ··· 359 354 const char *internal_name, 360 355 u32 * converted_name_length, char **converted_name); 361 356 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); 357 + struct acpi_namespace_node *acpi_ns_validate_handle(acpi_handle handle); 365 358 366 359 void acpi_ns_terminate(void); 367 360
+5 -1
drivers/acpi/acpica/acobject.h
··· 180 180 u8 sync_level; 181 181 union acpi_operand_object *mutex; 182 182 u8 *aml_start; 183 - ACPI_INTERNAL_METHOD implementation; 183 + union { 184 + ACPI_INTERNAL_METHOD implementation; 185 + union acpi_operand_object *handler; 186 + } extra; 187 + 184 188 u32 aml_length; 185 189 u8 thread_count; 186 190 acpi_owner_id owner_id;
+1 -1
drivers/acpi/acpica/dsmethod.c
··· 414 414 /* Invoke an internal method if necessary */ 415 415 416 416 if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { 417 - status = obj_desc->method.implementation(next_walk_state); 417 + status = obj_desc->method.extra.implementation(next_walk_state); 418 418 if (status == AE_OK) { 419 419 status = AE_CTRL_TERMINATE; 420 420 }
+39 -25
drivers/acpi/acpica/dswload.c
··· 212 212 case ACPI_TYPE_BUFFER: 213 213 214 214 /* 215 - * These types we will allow, but we will change the type. This 216 - * enables some existing code of the form: 215 + * These types we will allow, but we will change the type. 216 + * This enables some existing code of the form: 217 217 * 218 218 * Name (DEB, 0) 219 219 * Scope (DEB) { ... } 220 220 * 221 - * Note: silently change the type here. On the second pass, we will report 222 - * a warning 221 + * Note: silently change the type here. On the second pass, 222 + * we will report a warning 223 223 */ 224 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, 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), 227 228 acpi_ut_get_type_name(node->type))); 228 229 229 230 node->type = ACPI_TYPE_ANY; ··· 236 235 /* All other types are an error */ 237 236 238 237 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)); 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))); 241 242 242 243 return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 243 244 } ··· 700 697 case ACPI_TYPE_BUFFER: 701 698 702 699 /* 703 - * These types we will allow, but we will change the type. This 704 - * enables some existing code of the form: 700 + * These types we will allow, but we will change the type. 701 + * This enables some existing code of the form: 705 702 * 706 703 * Name (DEB, 0) 707 704 * Scope (DEB) { ... } 708 705 */ 709 706 ACPI_WARNING((AE_INFO, 710 - "Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)", 711 - buffer_ptr, 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), 712 710 acpi_ut_get_type_name(node->type))); 713 711 714 712 node->type = ACPI_TYPE_ANY; ··· 721 717 /* All other types are an error */ 722 718 723 719 ACPI_ERROR((AE_INFO, 724 - "Invalid type (%s) for target of Scope operator [%4.4s]", 720 + "Invalid type (%s) for target of " 721 + "Scope operator [%4.4s] (Cannot override)", 725 722 acpi_ut_get_type_name(node->type), 726 - buffer_ptr)); 723 + acpi_ut_get_node_name(node))); 727 724 728 725 return (AE_AML_OPERAND_TYPE); 729 726 } ··· 1052 1047 } 1053 1048 1054 1049 /* 1055 - * If we are executing a method, initialize the region 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. 1056 1060 */ 1057 1061 if (walk_state->method_node) { 1062 + /* 1063 + * Executing a method: initialize the region and unlock 1064 + * the interpreter 1065 + */ 1058 1066 status = 1059 1067 acpi_ex_create_region(op->named.data, 1060 1068 op->named.length, ··· 1076 1058 if (ACPI_FAILURE(status)) { 1077 1059 return (status); 1078 1060 } 1061 + 1062 + acpi_ex_exit_interpreter(); 1079 1063 } 1080 1064 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 1065 status = 1092 1066 acpi_ev_initialize_region 1093 1067 (acpi_ns_get_attached_object(node), FALSE); 1068 + if (walk_state->method_node) { 1069 + acpi_ex_enter_interpreter(); 1070 + } 1071 + 1094 1072 if (ACPI_FAILURE(status)) { 1095 1073 /* 1096 1074 * If AE_NOT_EXIST is returned, it is not fatal
+2 -2
drivers/acpi/acpica/evregion.c
··· 718 718 719 719 /* Convert and validate the device handle */ 720 720 721 - node = acpi_ns_map_handle_to_node(obj_handle); 721 + node = acpi_ns_validate_handle(obj_handle); 722 722 if (!node) { 723 723 return (AE_BAD_PARAMETER); 724 724 } ··· 1087 1087 1088 1088 /* Convert and validate the device handle */ 1089 1089 1090 - node = acpi_ns_map_handle_to_node(obj_handle); 1090 + node = acpi_ns_validate_handle(obj_handle); 1091 1091 if (!node) { 1092 1092 return (AE_BAD_PARAMETER); 1093 1093 }
+15
drivers/acpi/acpica/evrgnini.c
··· 575 575 handler_obj = obj_desc->thermal_zone.handler; 576 576 break; 577 577 578 + case ACPI_TYPE_METHOD: 579 + /* 580 + * If we are executing module level code, the original 581 + * Node's object was replaced by this Method object and we 582 + * saved the handler in the method object. 583 + * 584 + * See acpi_ns_exec_module_code 585 + */ 586 + if (obj_desc->method. 587 + flags & AOPOBJ_MODULE_LEVEL) { 588 + handler_obj = 589 + obj_desc->method.extra.handler; 590 + } 591 + break; 592 + 578 593 default: 579 594 /* Ignore other objects */ 580 595 break;
+2 -2
drivers/acpi/acpica/evxface.c
··· 259 259 260 260 /* Convert and validate the device handle */ 261 261 262 - node = acpi_ns_map_handle_to_node(device); 262 + node = acpi_ns_validate_handle(device); 263 263 if (!node) { 264 264 status = AE_BAD_PARAMETER; 265 265 goto unlock_and_exit; ··· 425 425 426 426 /* Convert and validate the device handle */ 427 427 428 - node = acpi_ns_map_handle_to_node(device); 428 + node = acpi_ns_validate_handle(device); 429 429 if (!node) { 430 430 status = AE_BAD_PARAMETER; 431 431 goto unlock_and_exit;
+2 -2
drivers/acpi/acpica/evxfevnt.c
··· 610 610 return (status); 611 611 } 612 612 613 - node = acpi_ns_map_handle_to_node(gpe_device); 613 + node = acpi_ns_validate_handle(gpe_device); 614 614 if (!node) { 615 615 status = AE_BAD_PARAMETER; 616 616 goto unlock_and_exit; ··· 698 698 return (status); 699 699 } 700 700 701 - node = acpi_ns_map_handle_to_node(gpe_device); 701 + node = acpi_ns_validate_handle(gpe_device); 702 702 if (!node) { 703 703 status = AE_BAD_PARAMETER; 704 704 goto unlock_and_exit;
+2 -2
drivers/acpi/acpica/evxfregn.c
··· 89 89 90 90 /* Convert and validate the device handle */ 91 91 92 - node = acpi_ns_map_handle_to_node(device); 92 + node = acpi_ns_validate_handle(device); 93 93 if (!node) { 94 94 status = AE_BAD_PARAMETER; 95 95 goto unlock_and_exit; ··· 155 155 156 156 /* Convert and validate the device handle */ 157 157 158 - node = acpi_ns_map_handle_to_node(device); 158 + node = acpi_ns_validate_handle(device); 159 159 if (!node || 160 160 ((node->type != ACPI_TYPE_DEVICE) && 161 161 (node->type != ACPI_TYPE_PROCESSOR) &&
+9 -9
drivers/acpi/acpica/exmutex.c
··· 375 375 return_ACPI_STATUS(AE_AML_MUTEX_NOT_ACQUIRED); 376 376 } 377 377 378 + /* Must have a valid thread ID */ 379 + 380 + if (!walk_state->thread) { 381 + ACPI_ERROR((AE_INFO, 382 + "Cannot release Mutex [%4.4s], null thread info", 383 + acpi_ut_get_node_name(obj_desc->mutex.node))); 384 + return_ACPI_STATUS(AE_AML_INTERNAL); 385 + } 386 + 378 387 /* 379 388 * The Mutex is owned, but this thread must be the owner. 380 389 * Special case for Global Lock, any thread can release ··· 399 390 obj_desc->mutex.owner_thread-> 400 391 thread_id))); 401 392 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 393 } 412 394 413 395 /*
+1 -1
drivers/acpi/acpica/nsaccess.c
··· 165 165 166 166 obj_desc->method.method_flags = 167 167 AML_METHOD_INTERNAL_ONLY; 168 - obj_desc->method.implementation = 168 + obj_desc->method.extra.implementation = 169 169 acpi_ut_osi_implementation; 170 170 #endif 171 171 break;
+1 -1
drivers/acpi/acpica/nsdump.c
··· 180 180 return (AE_OK); 181 181 } 182 182 183 - this_node = acpi_ns_map_handle_to_node(obj_handle); 183 + this_node = acpi_ns_validate_handle(obj_handle); 184 184 if (!this_node) { 185 185 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid object handle %p\n", 186 186 obj_handle));
+18
drivers/acpi/acpica/nseval.c
··· 381 381 method_obj->method.next_object); 382 382 type = acpi_ns_get_type(parent_node); 383 383 384 + /* 385 + * Get the region handler and save it in the method object. We may need 386 + * this if an operation region declaration causes a _REG method to be run. 387 + * 388 + * We can't do this in acpi_ps_link_module_code because 389 + * acpi_gbl_root_node->Object is NULL at PASS1. 390 + */ 391 + if ((type == ACPI_TYPE_DEVICE) && parent_node->object) { 392 + method_obj->method.extra.handler = 393 + parent_node->object->device.handler; 394 + } 395 + 384 396 /* Must clear next_object (acpi_ns_attach_object needs the field) */ 385 397 386 398 method_obj->method.next_object = NULL; ··· 426 414 427 415 ACPI_DEBUG_PRINT((ACPI_DB_INIT, "Executed module-level code at %p\n", 428 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 + } 429 423 430 424 /* Detach the temporary method object */ 431 425
+1 -1
drivers/acpi/acpica/nsnames.c
··· 232 232 233 233 ACPI_FUNCTION_TRACE_PTR(ns_handle_to_pathname, target_handle); 234 234 235 - node = acpi_ns_map_handle_to_node(target_handle); 235 + node = acpi_ns_validate_handle(target_handle); 236 236 if (!node) { 237 237 return_ACPI_STATUS(AE_BAD_PARAMETER); 238 238 }
+40 -59
drivers/acpi/acpica/nspredef.c
··· 216 216 data->pathname = pathname; 217 217 218 218 /* 219 - * Check that the type of the return object is what is expected for 220 - * this predefined name 219 + * Check that the type of the main return object is what is expected 220 + * for this predefined name 221 221 */ 222 222 status = acpi_ns_check_object_type(data, return_object_ptr, 223 223 predefined->info.expected_btypes, 224 224 ACPI_NOT_PACKAGE_ELEMENT); 225 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); 226 + goto exit; 233 227 } 234 228 235 229 /* 236 - * Perform additional, more complicated repairs on a per-name 237 - * basis. 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. 238 247 */ 239 248 status = acpi_ns_complex_repairs(data, node, status, return_object_ptr); 240 249 241 - check_validation_status: 250 + exit: 242 251 /* 243 252 * If the object validation failed or if we successfully repaired one 244 253 * or more objects, mark the parent node to suppress further warning ··· 436 427 data->pathname, package->ret_info.type, 437 428 return_object->package.count)); 438 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 + 439 437 /* Extract package count and elements array */ 440 438 441 439 elements = return_object->package.elements; ··· 477 461 if (count < expected_count) { 478 462 goto package_too_small; 479 463 } 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)); 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)); 485 469 } 486 470 487 471 /* Validate all elements of the returned package */ ··· 696 680 union acpi_operand_object *sub_package; 697 681 union acpi_operand_object **sub_elements; 698 682 acpi_status status; 699 - u8 non_trailing_null = FALSE; 700 683 u32 expected_count; 701 684 u32 i; 702 685 u32 j; 703 686 704 - /* Validate each sub-Package in the parent Package */ 705 - 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 + */ 706 694 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 695 sub_package = *elements; 747 696 sub_elements = sub_package->package.elements; 748 697
+398 -99
drivers/acpi/acpica/nsrepair.c
··· 45 45 #include "accommon.h" 46 46 #include "acnamesp.h" 47 47 #include "acinterp.h" 48 - #include "acpredef.h" 49 48 50 49 #define _COMPONENT ACPI_NAMESPACE 51 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); 52 91 53 92 /******************************************************************************* 54 93 * ··· 107 68 * not expected. 108 69 * 109 70 ******************************************************************************/ 71 + 110 72 acpi_status 111 73 acpi_ns_repair_object(struct acpi_predefined_data *data, 112 74 u32 expected_btypes, ··· 116 76 { 117 77 union acpi_operand_object *return_object = *return_object_ptr; 118 78 union acpi_operand_object *new_object; 119 - acpi_size length; 120 79 acpi_status status; 80 + 81 + ACPI_FUNCTION_NAME(ns_repair_object); 121 82 122 83 /* 123 84 * At this point, we know that the type of the returned object was not 124 85 * one of the expected types for this predefined name. Attempt to 125 - * repair the object. Only a limited number of repairs are possible. 86 + * repair the object by converting it to one of the expected object 87 + * types for this predefined name. 126 88 */ 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); 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; 134 93 } 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 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: 211 119 212 120 /* Object was successfully repaired */ 213 121 ··· 173 185 return_object->common.reference_count--; 174 186 } 175 187 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)); 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)); 182 194 } 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))); 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))); 189 200 } 190 201 191 202 /* Delete old object, install the new return object */ ··· 192 205 acpi_ut_remove_reference(return_object); 193 206 *return_object_ptr = new_object; 194 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; 195 517 return (AE_OK); 196 518 } 197 519 ··· 534 238 { 535 239 union acpi_operand_object *pkg_obj_desc; 536 240 241 + ACPI_FUNCTION_NAME(ns_repair_package_list); 242 + 537 243 /* 538 244 * Create the new outer package and populate it. The new package will 539 245 * have a single element, the lone subpackage. ··· 552 254 *obj_desc_ptr = pkg_obj_desc; 553 255 data->flags |= ACPI_OBJECT_REPAIRED; 554 256 555 - ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, data->node_flags, 556 - "Repaired Incorrectly formed Package")); 257 + ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 258 + "%s: Repaired incorrectly formed Package\n", 259 + data->pathname)); 557 260 558 261 return (AE_OK); 559 262 }
+156 -39
drivers/acpi/acpica/nsrepair2.c
··· 45 45 #include <acpi/acpi.h> 46 46 #include "accommon.h" 47 47 #include "acnamesp.h" 48 + #include "acpredef.h" 48 49 49 50 #define _COMPONENT ACPI_NAMESPACE 50 51 ACPI_MODULE_NAME("nsrepair2") ··· 75 74 union acpi_operand_object **return_object_ptr); 76 75 77 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 78 81 acpi_ns_repair_PSS(struct acpi_predefined_data *data, 79 82 union acpi_operand_object **return_object_ptr); 80 83 ··· 94 89 u8 sort_direction, char *sort_key_name); 95 90 96 91 static acpi_status 97 - acpi_ns_remove_null_elements(union acpi_operand_object *package); 98 - 99 - static acpi_status 100 92 acpi_ns_sort_list(union acpi_operand_object **elements, 101 93 u32 count, u32 index, u8 sort_direction); 102 94 ··· 106 104 * This table contains the names of the predefined methods for which we can 107 105 * perform more complex repairs. 108 106 * 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 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 112 114 */ 113 115 static const struct acpi_repair_info acpi_ns_repairable_names[] = { 114 116 {"_ALR", acpi_ns_repair_ALR}, 117 + {"_FDE", acpi_ns_repair_FDE}, 118 + {"_GTM", acpi_ns_repair_FDE}, /* _GTM has same repair as _FDE */ 115 119 {"_PSS", acpi_ns_repair_PSS}, 116 120 {"_TSS", acpi_ns_repair_TSS}, 117 121 {{0, 0, 0, 0}, NULL} /* Table terminator */ 118 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)) 119 127 120 128 /****************************************************************************** 121 129 * ··· 223 211 "AmbientIlluminance"); 224 212 225 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); 226 302 } 227 303 228 304 /****************************************************************************** ··· 445 345 u32 previous_value; 446 346 acpi_status status; 447 347 348 + ACPI_FUNCTION_NAME(ns_check_sorted_list); 349 + 448 350 /* The top-level object must be a package */ 449 351 450 352 if (return_object->common.type != ACPI_TYPE_PACKAGE) { ··· 454 352 } 455 353 456 354 /* 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. 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. 462 358 */ 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 359 outer_elements = return_object->package.elements; 476 360 outer_element_count = return_object->package.count; 477 361 if (!outer_element_count) { ··· 510 422 511 423 data->flags |= ACPI_OBJECT_REPAIRED; 512 424 513 - ACPI_INFO_PREDEFINED((AE_INFO, data->pathname, 514 - data->node_flags, 515 - "Repaired unsorted list - now sorted by %s", 516 - sort_key_name)); 425 + ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, 426 + "%s: Repaired unsorted list - now sorted by %s\n", 427 + data->pathname, sort_key_name)); 517 428 return (AE_OK); 518 429 } 519 430 ··· 527 440 * 528 441 * FUNCTION: acpi_ns_remove_null_elements 529 442 * 530 - * PARAMETERS: obj_desc - A Package object 443 + * PARAMETERS: Data - Pointer to validation data structure 444 + * package_type - An acpi_return_package_types value 445 + * obj_desc - A Package object 531 446 * 532 - * RETURN: Status. AE_NULL_ENTRY means that one or more elements were 533 - * removed. 447 + * RETURN: None. 534 448 * 535 - * DESCRIPTION: Remove all NULL package elements and update the package count. 449 + * DESCRIPTION: Remove all NULL package elements from packages that contain 450 + * a variable number of sub-packages. 536 451 * 537 452 *****************************************************************************/ 538 453 539 - static acpi_status 540 - acpi_ns_remove_null_elements(union acpi_operand_object *obj_desc) 454 + void 455 + acpi_ns_remove_null_elements(struct acpi_predefined_data *data, 456 + u8 package_type, 457 + union acpi_operand_object *obj_desc) 541 458 { 542 459 union acpi_operand_object **source; 543 460 union acpi_operand_object **dest; 544 - acpi_status status = AE_OK; 545 461 u32 count; 546 462 u32 new_count; 547 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 + } 548 489 549 490 count = obj_desc->package.count; 550 491 new_count = count; ··· 580 465 source = obj_desc->package.elements; 581 466 dest = source; 582 467 583 - /* Examine all elements of the package object */ 468 + /* Examine all elements of the package object, remove nulls */ 584 469 585 470 for (i = 0; i < count; i++) { 586 471 if (!*source) { 587 - status = AE_NULL_ENTRY; 588 472 new_count--; 589 473 } else { 590 474 *dest = *source; ··· 592 478 source++; 593 479 } 594 480 595 - if (status == AE_NULL_ENTRY) { 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))); 596 487 597 488 /* NULL terminate list and update the package count */ 598 489 599 490 *dest = NULL; 600 491 obj_desc->package.count = new_count; 601 492 } 602 - 603 - return (status); 604 493 } 605 494 606 495 /******************************************************************************
+11 -46
drivers/acpi/acpica/nsutils.c
··· 671 671 672 672 /******************************************************************************* 673 673 * 674 - * FUNCTION: acpi_ns_map_handle_to_node 674 + * FUNCTION: acpi_ns_validate_handle 675 675 * 676 - * PARAMETERS: Handle - Handle to be converted to an Node 676 + * PARAMETERS: Handle - Handle to be validated and typecast to a 677 + * namespace node. 677 678 * 678 - * RETURN: A Name table entry pointer 679 + * RETURN: A pointer to a namespace node 679 680 * 680 - * DESCRIPTION: Convert a namespace handle to a real Node 681 + * DESCRIPTION: Convert a namespace handle to a namespace node. Handles special 682 + * cases for the root node. 681 683 * 682 - * Note: Real integer handles would allow for more verification 684 + * NOTE: Real integer handles would allow for more verification 683 685 * 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. 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. 688 689 * 689 690 ******************************************************************************/ 690 691 691 - struct acpi_namespace_node *acpi_ns_map_handle_to_node(acpi_handle handle) 692 + struct acpi_namespace_node *acpi_ns_validate_handle(acpi_handle handle) 692 693 { 693 694 694 695 ACPI_FUNCTION_ENTRY(); ··· 707 706 } 708 707 709 708 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 709 } 747 710 748 711 /*******************************************************************************
+5 -5
drivers/acpi/acpica/nsxfeval.c
··· 190 190 191 191 /* Convert and validate the device handle */ 192 192 193 - info->prefix_node = acpi_ns_map_handle_to_node(handle); 193 + info->prefix_node = acpi_ns_validate_handle(handle); 194 194 if (!info->prefix_node) { 195 195 status = AE_BAD_PARAMETER; 196 196 goto cleanup; ··· 552 552 return (status); 553 553 } 554 554 555 - node = acpi_ns_map_handle_to_node(obj_handle); 555 + node = acpi_ns_validate_handle(obj_handle); 556 556 status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 557 557 if (ACPI_FAILURE(status)) { 558 558 return (status); ··· 729 729 730 730 /* Convert and validate the handle */ 731 731 732 - node = acpi_ns_map_handle_to_node(obj_handle); 732 + node = acpi_ns_validate_handle(obj_handle); 733 733 if (!node) { 734 734 status = AE_BAD_PARAMETER; 735 735 goto unlock_and_exit; ··· 775 775 776 776 /* Convert and validate the handle */ 777 777 778 - node = acpi_ns_map_handle_to_node(obj_handle); 778 + node = acpi_ns_validate_handle(obj_handle); 779 779 if (!node) { 780 780 status = AE_BAD_PARAMETER; 781 781 goto unlock_and_exit; ··· 822 822 823 823 /* Convert and validate the handle */ 824 824 825 - node = acpi_ns_map_handle_to_node(obj_handle); 825 + node = acpi_ns_validate_handle(obj_handle); 826 826 if (!node) { 827 827 status = AE_BAD_PARAMETER; 828 828 goto unlock_and_exit;
+5 -5
drivers/acpi/acpica/nsxfname.c
··· 93 93 /* Convert a parent handle to a prefix node */ 94 94 95 95 if (parent) { 96 - prefix_node = acpi_ns_map_handle_to_node(parent); 96 + prefix_node = acpi_ns_validate_handle(parent); 97 97 if (!prefix_node) { 98 98 return (AE_BAD_PARAMETER); 99 99 } ··· 114 114 115 115 if (!ACPI_STRCMP(pathname, ACPI_NS_ROOT_PATH)) { 116 116 *ret_handle = 117 - acpi_ns_convert_entry_to_handle(acpi_gbl_root_node); 117 + ACPI_CAST_PTR(acpi_handle, acpi_gbl_root_node); 118 118 return (AE_OK); 119 119 } 120 120 } else if (!prefix_node) { ··· 129 129 status = 130 130 acpi_ns_get_node(prefix_node, pathname, ACPI_NS_NO_UPSEARCH, &node); 131 131 if (ACPI_SUCCESS(status)) { 132 - *ret_handle = acpi_ns_convert_entry_to_handle(node); 132 + *ret_handle = ACPI_CAST_PTR(acpi_handle, node); 133 133 } 134 134 135 135 return (status); ··· 186 186 return (status); 187 187 } 188 188 189 - node = acpi_ns_map_handle_to_node(handle); 189 + node = acpi_ns_validate_handle(handle); 190 190 if (!node) { 191 191 status = AE_BAD_PARAMETER; 192 192 goto unlock_and_exit; ··· 291 291 goto cleanup; 292 292 } 293 293 294 - node = acpi_ns_map_handle_to_node(handle); 294 + node = acpi_ns_validate_handle(handle); 295 295 if (!node) { 296 296 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 297 297 return (AE_BAD_PARAMETER);
+7 -7
drivers/acpi/acpica/nsxfobj.c
··· 79 79 80 80 /* Convert and validate the handle */ 81 81 82 - node = acpi_ns_map_handle_to_node(handle); 82 + node = acpi_ns_validate_handle(handle); 83 83 if (!node) { 84 84 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 85 85 return (AE_BAD_PARAMETER); ··· 132 132 133 133 /* Convert and validate the handle */ 134 134 135 - node = acpi_ns_map_handle_to_node(handle); 135 + node = acpi_ns_validate_handle(handle); 136 136 if (!node) { 137 137 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 138 138 return (AE_BAD_PARAMETER); ··· 182 182 183 183 /* Convert and validate the handle */ 184 184 185 - node = acpi_ns_map_handle_to_node(handle); 185 + node = acpi_ns_validate_handle(handle); 186 186 if (!node) { 187 187 status = AE_BAD_PARAMETER; 188 188 goto unlock_and_exit; ··· 191 191 /* Get the parent entry */ 192 192 193 193 parent_node = acpi_ns_get_parent_node(node); 194 - *ret_handle = acpi_ns_convert_entry_to_handle(parent_node); 194 + *ret_handle = ACPI_CAST_PTR(acpi_handle, parent_node); 195 195 196 196 /* Return exception if parent is null */ 197 197 ··· 251 251 252 252 /* Start search at the beginning of the specified scope */ 253 253 254 - parent_node = acpi_ns_map_handle_to_node(parent); 254 + parent_node = acpi_ns_validate_handle(parent); 255 255 if (!parent_node) { 256 256 status = AE_BAD_PARAMETER; 257 257 goto unlock_and_exit; ··· 260 260 /* Non-null handle, ignore the parent */ 261 261 /* Convert and validate the handle */ 262 262 263 - child_node = acpi_ns_map_handle_to_node(child); 263 + child_node = acpi_ns_validate_handle(child); 264 264 if (!child_node) { 265 265 status = AE_BAD_PARAMETER; 266 266 goto unlock_and_exit; ··· 276 276 } 277 277 278 278 if (ret_handle) { 279 - *ret_handle = acpi_ns_convert_entry_to_handle(node); 279 + *ret_handle = ACPI_CAST_PTR(acpi_handle, node); 280 280 } 281 281 282 282 unlock_and_exit:
+2 -1
drivers/acpi/acpica/psxface.c
··· 287 287 /* Invoke an internal method if necessary */ 288 288 289 289 if (info->obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { 290 - status = info->obj_desc->method.implementation(walk_state); 290 + status = 291 + info->obj_desc->method.extra.implementation(walk_state); 291 292 info->return_object = walk_state->return_desc; 292 293 293 294 /* Cleanup states */
+1 -1
drivers/acpi/acpica/rsxface.c
··· 104 104 return_ACPI_STATUS(AE_BAD_PARAMETER); 105 105 } 106 106 107 - node = acpi_ns_map_handle_to_node(device_handle); 107 + node = acpi_ns_validate_handle(device_handle); 108 108 if (!node) { 109 109 return_ACPI_STATUS(AE_BAD_PARAMETER); 110 110 }
+14 -13
drivers/acpi/acpica/utcopy.c
··· 323 323 * RETURN: Status 324 324 * 325 325 * DESCRIPTION: This function is called to place a package object in a user 326 - * buffer. A package object by definition contains other objects. 326 + * buffer. A package object by definition contains other objects. 327 327 * 328 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. 329 + * The caller must have verified the buffer length needed using 330 + * the acpi_ut_get_object_size function before calling this function. 331 331 * 332 332 ******************************************************************************/ 333 333 ··· 382 382 * FUNCTION: acpi_ut_copy_iobject_to_eobject 383 383 * 384 384 * PARAMETERS: internal_object - The internal object to be converted 385 - * buffer_ptr - Where the object is returned 385 + * ret_buffer - Where the object is returned 386 386 * 387 387 * RETURN: Status 388 388 * 389 - * DESCRIPTION: This function is called to build an API object to be returned to 390 - * the caller. 389 + * DESCRIPTION: This function is called to build an API object to be returned 390 + * to the caller. 391 391 * 392 392 ******************************************************************************/ 393 393 ··· 626 626 * PARAMETERS: external_object - The external object to be converted 627 627 * internal_object - Where the internal object is returned 628 628 * 629 - * RETURN: Status - the status of the call 629 + * RETURN: Status 630 630 * 631 631 * DESCRIPTION: Converts an external object to an internal object. 632 632 * ··· 665 665 * 666 666 * RETURN: Status 667 667 * 668 - * DESCRIPTION: Simple copy of one internal object to another. Reference count 668 + * DESCRIPTION: Simple copy of one internal object to another. Reference count 669 669 * of the destination object is preserved. 670 670 * 671 671 ******************************************************************************/ ··· 897 897 * 898 898 * FUNCTION: acpi_ut_copy_ipackage_to_ipackage 899 899 * 900 - * PARAMETERS: *source_obj - Pointer to the source package object 901 - * *dest_obj - Where the internal object is returned 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 902 903 * 903 - * RETURN: Status - the status of the call 904 + * RETURN: Status 904 905 * 905 906 * DESCRIPTION: This function is called to copy an internal package object 906 907 * into another internal package object. ··· 954 953 * 955 954 * FUNCTION: acpi_ut_copy_iobject_to_iobject 956 955 * 957 - * PARAMETERS: walk_state - Current walk state 958 - * source_desc - The internal object to be copied 956 + * PARAMETERS: source_desc - The internal object to be copied 959 957 * dest_desc - Where the copied object is returned 958 + * walk_state - Current walk state 960 959 * 961 960 * RETURN: Status 962 961 *
+1 -1
drivers/acpi/battery.c
··· 831 831 dev_name(&device->dev), event, 832 832 acpi_battery_present(battery)); 833 833 #ifdef CONFIG_ACPI_SYSFS_POWER 834 - /* acpi_batter_update could remove power_supply object */ 834 + /* acpi_battery_update could remove power_supply object */ 835 835 if (battery->bat.dev) 836 836 kobject_uevent(&battery->bat.dev->kobj, KOBJ_CHANGE); 837 837 #endif
+148
drivers/acpi/bus.c
··· 344 344 345 345 EXPORT_SYMBOL(acpi_bus_can_wakeup); 346 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 + 347 493 /* -------------------------------------------------------------------------- 348 494 Event Management 349 495 -------------------------------------------------------------------------- */ ··· 879 733 */ 880 734 status = acpi_ec_ecdt_probe(); 881 735 /* Ignore result. Not having an ECDT is not fatal. */ 736 + 737 + acpi_bus_osc_support(); 882 738 883 739 status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION); 884 740 if (ACPI_FAILURE(status)) {
+7
drivers/acpi/button.c
··· 282 282 if (ret == NOTIFY_DONE) 283 283 ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, 284 284 device); 285 + if (ret == NOTIFY_DONE || ret == NOTIFY_OK) { 286 + /* 287 + * It is also regarded as success if the notifier_chain 288 + * returns NOTIFY_OK or NOTIFY_DONE. 289 + */ 290 + ret = 0; 291 + } 285 292 return ret; 286 293 } 287 294
+83 -1
drivers/acpi/debug.c
··· 8 8 #include <linux/module.h> 9 9 #include <linux/kernel.h> 10 10 #include <linux/moduleparam.h> 11 + #include <linux/debugfs.h> 11 12 #include <asm/uaccess.h> 12 13 #include <acpi/acpi_drivers.h> 13 14 ··· 197 196 NULL, 0644); 198 197 199 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 + /* -------------------------------------------------------------------------- 200 273 FS Interface (/proc) 201 274 -------------------------------------------------------------------------- */ 202 275 #ifdef CONFIG_ACPI_PROCFS ··· 361 286 }; 362 287 #endif 363 288 364 - int __init acpi_debug_init(void) 289 + int __init acpi_procfs_init(void) 365 290 { 366 291 #ifdef CONFIG_ACPI_PROCFS 367 292 struct proc_dir_entry *entry; ··· 395 320 #else 396 321 return 0; 397 322 #endif 323 + } 324 + 325 + int __init acpi_debug_init(void) 326 + { 327 + acpi_debugfs_init(); 328 + acpi_procfs_init(); 329 + return 0; 398 330 }
+92 -171
drivers/acpi/dock.c
··· 50 50 " before undocking"); 51 51 52 52 static struct atomic_notifier_head dock_notifier_list; 53 - static char dock_device_name[] = "dock"; 54 53 55 54 static const struct acpi_device_id dock_device_ids[] = { 56 55 {"LNXDOCK", 0}, ··· 92 93 * Dock Dependent device functions * 93 94 *****************************************************************************/ 94 95 /** 95 - * alloc_dock_dependent_device - allocate and init a dependent device 96 - * @handle: the acpi_handle of the dependent device 96 + * add_dock_dependent_device - associate a device with the dock station 97 + * @ds: The dock station 98 + * @handle: handle of the dependent device 97 99 * 98 - * Allocate memory for a dependent device structure for a device referenced 99 - * by the acpi handle 100 + * Add the dependent device to the dock's dependent device list. 100 101 */ 101 - static struct dock_dependent_device * 102 - alloc_dock_dependent_device(acpi_handle handle) 102 + static int 103 + add_dock_dependent_device(struct dock_station *ds, acpi_handle handle) 103 104 { 104 105 struct dock_dependent_device *dd; 105 106 106 107 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 - } 108 + if (!dd) 109 + return -ENOMEM; 114 110 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 - { 111 + dd->handle = handle; 112 + INIT_LIST_HEAD(&dd->list); 113 + INIT_LIST_HEAD(&dd->hotplug_list); 114 + 126 115 spin_lock(&ds->dd_lock); 127 116 list_add_tail(&dd->list, &ds->dependent_devices); 128 117 spin_unlock(&ds->dd_lock); 118 + 119 + return 0; 129 120 } 130 121 131 122 /** ··· 238 249 static int is_ejectable_bay(acpi_handle handle) 239 250 { 240 251 acpi_handle phandle; 252 + 241 253 if (!is_ejectable(handle)) 242 254 return 0; 243 255 if (is_battery(handle) || is_ata(handle)) ··· 265 275 266 276 if (is_dock(handle)) 267 277 return 1; 268 - list_for_each_entry(dock_station, &dock_stations, sibling) { 278 + 279 + list_for_each_entry(dock_station, &dock_stations, sibling) 269 280 if (find_dock_dependent_device(dock_station, handle)) 270 281 return 1; 271 - } 272 282 273 283 return 0; 274 284 } 275 - 276 285 EXPORT_SYMBOL_GPL(is_dock_device); 277 286 278 287 /** ··· 294 305 return 0; 295 306 } 296 307 297 - 298 - 299 308 /** 300 309 * dock_create_acpi_device - add new devices to acpi 301 310 * @handle - handle of the device to add ··· 307 320 */ 308 321 static struct acpi_device * dock_create_acpi_device(acpi_handle handle) 309 322 { 310 - struct acpi_device *device = NULL; 323 + struct acpi_device *device; 311 324 struct acpi_device *parent_device; 312 325 acpi_handle parent; 313 326 int ret; ··· 324 337 ret = acpi_bus_add(&device, parent_device, handle, 325 338 ACPI_BUS_TYPE_DEVICE); 326 339 if (ret) { 327 - pr_debug("error adding bus, %x\n", 328 - -ret); 340 + pr_debug("error adding bus, %x\n", -ret); 329 341 return NULL; 330 342 } 331 343 } ··· 350 364 } 351 365 } 352 366 353 - 354 367 /** 355 368 * hotplug_dock_devices - insert or remove devices on the dock station 356 369 * @ds: the dock station ··· 369 384 /* 370 385 * First call driver specific hotplug functions 371 386 */ 372 - list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list) { 387 + list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list) 373 388 if (dd->ops && dd->ops->handler) 374 389 dd->ops->handler(dd->handle, event, dd->context); 375 - } 376 390 377 391 /* 378 392 * Now make sure that an acpi_device is created for each ··· 410 426 list_for_each_entry(dd, &ds->hotplug_devices, hotplug_list) 411 427 if (dd->ops && dd->ops->uevent) 412 428 dd->ops->uevent(dd->handle, event, dd->context); 429 + 413 430 if (num != DOCK_EVENT) 414 431 kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); 415 432 } ··· 441 456 arg.type = ACPI_TYPE_INTEGER; 442 457 arg.integer.value = 1; 443 458 444 - if (ACPI_FAILURE(acpi_evaluate_object(ds->handle, "_EJ0", 445 - &arg_list, NULL))) 459 + status = acpi_evaluate_object(ds->handle, "_EJ0", &arg_list, NULL); 460 + if (ACPI_FAILURE(status)) 446 461 pr_debug("Failed to evaluate _EJ0!\n"); 447 462 } 448 463 ··· 562 577 563 578 return atomic_notifier_chain_register(&dock_notifier_list, nb); 564 579 } 565 - 566 580 EXPORT_SYMBOL_GPL(register_dock_notifier); 567 581 568 582 /** ··· 575 591 576 592 atomic_notifier_chain_unregister(&dock_notifier_list, nb); 577 593 } 578 - 579 594 EXPORT_SYMBOL_GPL(unregister_dock_notifier); 580 595 581 596 /** ··· 619 636 620 637 return ret; 621 638 } 622 - 623 639 EXPORT_SYMBOL_GPL(register_hotplug_dock_device); 624 640 625 641 /** ··· 639 657 dock_del_hotplug_device(dock_station, dd); 640 658 } 641 659 } 642 - 643 660 EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device); 644 661 645 662 /** ··· 753 772 754 773 static void acpi_dock_deferred_cb(void *context) 755 774 { 756 - struct dock_data *data = (struct dock_data *)context; 775 + struct dock_data *data = context; 757 776 758 777 dock_notify(data->handle, data->event, data->ds); 759 778 kfree(data); ··· 763 782 unsigned long event, void *data) 764 783 { 765 784 struct dock_station *dock_station; 766 - acpi_handle handle = (acpi_handle)data; 785 + acpi_handle handle = data; 767 786 768 787 if (event != ACPI_NOTIFY_BUS_CHECK && event != ACPI_NOTIFY_DEVICE_CHECK 769 788 && event != ACPI_NOTIFY_EJECT_REQUEST) 770 789 return 0; 771 790 list_for_each_entry(dock_station, &dock_stations, sibling) { 772 791 if (dock_station->handle == handle) { 773 - struct dock_data *dock_data; 792 + struct dock_data *dd; 774 793 775 - dock_data = kmalloc(sizeof(*dock_data), GFP_KERNEL); 776 - if (!dock_data) 794 + dd = kmalloc(sizeof(*dd), GFP_KERNEL); 795 + if (!dd) 777 796 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); 797 + dd->handle = handle; 798 + dd->event = event; 799 + dd->ds = dock_station; 800 + acpi_os_hotplug_execute(acpi_dock_deferred_cb, dd); 783 801 return 0 ; 784 802 } 785 803 } ··· 806 826 acpi_status status; 807 827 acpi_handle tmp, parent; 808 828 struct dock_station *ds = context; 809 - struct dock_dependent_device *dd; 810 829 811 830 status = acpi_bus_get_ejd(handle, &tmp); 812 831 if (ACPI_FAILURE(status)) { ··· 819 840 goto fdd_out; 820 841 } 821 842 822 - if (tmp == ds->handle) { 823 - dd = alloc_dock_dependent_device(handle); 824 - if (dd) 825 - add_dock_dependent_device(ds, dd); 826 - } 843 + if (tmp == ds->handle) 844 + add_dock_dependent_device(ds, handle); 845 + 827 846 fdd_out: 828 847 return AE_OK; 829 848 } ··· 834 857 { 835 858 struct acpi_device *tmp; 836 859 837 - struct dock_station *dock_station = *((struct dock_station **) 838 - dev->platform_data); 860 + struct dock_station *dock_station = dev->platform_data; 839 861 840 862 if (ACPI_SUCCESS(acpi_bus_get_device(dock_station->handle, &tmp))) 841 863 return snprintf(buf, PAGE_SIZE, "1\n"); ··· 848 872 static ssize_t show_flags(struct device *dev, 849 873 struct device_attribute *attr, char *buf) 850 874 { 851 - struct dock_station *dock_station = *((struct dock_station **) 852 - dev->platform_data); 875 + struct dock_station *dock_station = dev->platform_data; 853 876 return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags); 854 877 855 878 } ··· 861 886 const char *buf, size_t count) 862 887 { 863 888 int ret; 864 - struct dock_station *dock_station = *((struct dock_station **) 865 - dev->platform_data); 889 + struct dock_station *dock_station = dev->platform_data; 866 890 867 891 if (!count) 868 892 return -EINVAL; ··· 879 905 struct device_attribute *attr, char *buf) 880 906 { 881 907 unsigned long long lbuf; 882 - struct dock_station *dock_station = *((struct dock_station **) 883 - dev->platform_data); 908 + struct dock_station *dock_station = dev->platform_data; 884 909 acpi_status status = acpi_evaluate_integer(dock_station->handle, 885 910 "_UID", NULL, &lbuf); 886 911 if (ACPI_FAILURE(status)) ··· 892 919 static ssize_t show_dock_type(struct device *dev, 893 920 struct device_attribute *attr, char *buf) 894 921 { 895 - struct dock_station *dock_station = *((struct dock_station **) 896 - dev->platform_data); 922 + struct dock_station *dock_station = dev->platform_data; 897 923 char *type; 898 924 899 925 if (dock_station->flags & DOCK_IS_DOCK) ··· 908 936 } 909 937 static DEVICE_ATTR(type, S_IRUGO, show_dock_type, NULL); 910 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 + 911 952 /** 912 953 * dock_add - add a new dock station 913 954 * @handle: the dock station handle ··· 930 945 */ 931 946 static int dock_add(acpi_handle handle) 932 947 { 933 - int ret; 934 - struct dock_dependent_device *dd; 935 - struct dock_station *dock_station; 936 - struct platform_device *dock_device; 948 + int ret, id; 949 + struct dock_station ds, *dock_station; 950 + struct platform_device *dd; 937 951 938 - /* allocate & initialize the dock_station private data */ 939 - dock_station = kzalloc(sizeof(*dock_station), GFP_KERNEL); 940 - if (!dock_station) 941 - return -ENOMEM; 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 + 942 959 dock_station->handle = handle; 960 + dock_station->dock_device = dd; 943 961 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 962 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 + 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); 963 969 964 970 /* we want the dock device to send uevents */ 965 - dev_set_uevent_suppress(&dock_device->dev, 0); 971 + dev_set_uevent_suppress(&dd->dev, 0); 966 972 967 973 if (is_dock(handle)) 968 974 dock_station->flags |= DOCK_IS_DOCK; ··· 962 986 if (is_battery(handle)) 963 987 dock_station->flags |= DOCK_IS_BAT; 964 988 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); 989 + ret = sysfs_create_group(&dd->dev.kobj, &dock_attribute_group); 1004 990 if (ret) 1005 - printk(KERN_ERR"Error %d adding sysfs file\n", ret); 991 + goto err_unregister; 1006 992 1007 993 /* Find dependent devices */ 1008 994 acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ··· 972 1034 dock_station, NULL); 973 1035 974 1036 /* 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); 1037 + ret = add_dock_dependent_device(dock_station, handle); 1038 + if (ret) 1039 + goto err_rmgroup; 983 1040 984 1041 dock_station_count++; 985 1042 list_add(&dock_station->sibling, &dock_stations); 986 1043 return 0; 987 1044 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; 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); 997 1050 return ret; 998 1051 } 999 1052 1000 1053 /** 1001 1054 * dock_remove - free up resources related to the dock station 1002 1055 */ 1003 - static int dock_remove(struct dock_station *dock_station) 1056 + static int dock_remove(struct dock_station *ds) 1004 1057 { 1005 1058 struct dock_dependent_device *dd, *tmp; 1006 - struct platform_device *dock_device = dock_station->dock_device; 1059 + struct platform_device *dock_device = ds->dock_device; 1007 1060 1008 1061 if (!dock_station_count) 1009 1062 return 0; 1010 1063 1011 1064 /* remove dependent devices */ 1012 - list_for_each_entry_safe(dd, tmp, &dock_station->dependent_devices, 1013 - list) 1014 - kfree(dd); 1065 + list_for_each_entry_safe(dd, tmp, &ds->dependent_devices, list) 1066 + kfree(dd); 1067 + 1068 + list_del(&ds->sibling); 1015 1069 1016 1070 /* 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); 1071 + sysfs_remove_group(&dock_device->dev.kobj, &dock_attribute_group); 1022 1072 platform_device_unregister(dock_device); 1023 1073 1024 - /* free dock station memory */ 1025 - kfree(dock_station); 1026 - dock_station = NULL; 1027 1074 return 0; 1028 1075 } 1029 1076 ··· 1026 1103 { 1027 1104 acpi_status status = AE_OK; 1028 1105 1029 - if (is_dock(handle)) { 1030 - if (dock_add(handle) >= 0) { 1106 + if (is_dock(handle)) 1107 + if (dock_add(handle) >= 0) 1031 1108 status = AE_CTRL_TERMINATE; 1032 - } 1033 - } 1109 + 1034 1110 return status; 1035 1111 } 1036 1112 ··· 1067 1145 1068 1146 static void __exit dock_exit(void) 1069 1147 { 1070 - struct dock_station *dock_station; 1071 - struct dock_station *tmp; 1148 + struct dock_station *tmp, *dock_station; 1072 1149 1073 1150 unregister_acpi_bus_notifier(&dock_acpi_notifier); 1074 1151 list_for_each_entry_safe(dock_station, tmp, &dock_stations, sibling)
+1 -1
drivers/acpi/fan.c
··· 267 267 goto end; 268 268 } 269 269 270 - dev_info(&device->dev, "registered as cooling_device%d\n", cdev->id); 270 + dev_dbg(&device->dev, "registered as cooling_device%d\n", cdev->id); 271 271 272 272 device->driver_data = cdev; 273 273 result = sysfs_create_link(&device->dev.kobj,
+6 -15
drivers/acpi/numa.c
··· 28 28 #include <linux/types.h> 29 29 #include <linux/errno.h> 30 30 #include <linux/acpi.h> 31 + #include <linux/numa.h> 31 32 #include <acpi/acpi_bus.h> 32 33 33 34 #define PREFIX "ACPI: " ··· 41 40 42 41 /* maps to convert between proximity domain and logical node ID */ 43 42 static int pxm_to_node_map[MAX_PXM_DOMAINS] 44 - = { [0 ... MAX_PXM_DOMAINS - 1] = NID_INVAL }; 43 + = { [0 ... MAX_PXM_DOMAINS - 1] = NUMA_NO_NODE }; 45 44 static int node_to_pxm_map[MAX_NUMNODES] 46 - = { [0 ... MAX_NUMNODES - 1] = PXM_INVAL }; 45 + = { [0 ... MAX_NUMNODES - 1] = PXM_INVAL }; 47 46 48 47 int pxm_to_node(int pxm) 49 48 { 50 49 if (pxm < 0) 51 - return NID_INVAL; 50 + return NUMA_NO_NODE; 52 51 return pxm_to_node_map[pxm]; 53 52 } 54 53 ··· 69 68 { 70 69 int node = pxm_to_node_map[pxm]; 71 70 72 - if (node < 0){ 71 + if (node < 0) { 73 72 if (nodes_weight(nodes_found_map) >= MAX_NUMNODES) 74 - return NID_INVAL; 73 + return NUMA_NO_NODE; 75 74 node = first_unset_node(nodes_found_map); 76 75 __acpi_map_pxm_to_node(pxm, node); 77 76 node_set(node, nodes_found_map); ··· 79 78 80 79 return node; 81 80 } 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 81 93 82 static void __init 94 83 acpi_table_print_srat_entry(struct acpi_subtable_header *header)
+1 -1
drivers/acpi/osl.c
··· 1118 1118 1119 1119 /* Check for resource conflicts between ACPI OperationRegions and native 1120 1120 * drivers */ 1121 - int acpi_check_resource_conflict(struct resource *res) 1121 + int acpi_check_resource_conflict(const struct resource *res) 1122 1122 { 1123 1123 struct acpi_res_list *res_list_elem; 1124 1124 int ioport;
+14 -62
drivers/acpi/pci_root.c
··· 202 202 } 203 203 } 204 204 205 - static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40, 206 - 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66}; 205 + static u8 pci_osc_uuid_str[] = "33DB4D5B-1FF7-401C-9657-7441C03DD766"; 207 206 208 207 static acpi_status acpi_pci_run_osc(acpi_handle handle, 209 208 const u32 *capbuf, u32 *retval) 210 209 { 210 + struct acpi_osc_context context = { 211 + .uuid_str = pci_osc_uuid_str, 212 + .rev = 1, 213 + .cap.length = 12, 214 + .cap.pointer = (void *)capbuf, 215 + }; 211 216 acpi_status status; 212 - struct acpi_object_list input; 213 - union acpi_object in_params[4]; 214 - struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; 215 - union acpi_object *out_obj; 216 - u32 errors; 217 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; 218 + status = acpi_run_osc(handle, &context); 219 + if (ACPI_SUCCESS(status)) { 220 + *retval = *((u32 *)(context.ret.pointer + 8)); 221 + kfree(context.ret.pointer); 244 222 } 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 223 return status; 272 224 } 273 225 ··· 229 277 u32 support_set, result, capbuf[3]; 230 278 231 279 /* do _OSC query for all possible controls */ 232 - support_set = root->osc_support_set | (flags & OSC_SUPPORT_MASKS); 280 + support_set = root->osc_support_set | (flags & OSC_PCI_SUPPORT_MASKS); 233 281 capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; 234 282 capbuf[OSC_SUPPORT_TYPE] = support_set; 235 - capbuf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS; 283 + capbuf[OSC_CONTROL_TYPE] = OSC_PCI_CONTROL_MASKS; 236 284 237 285 status = acpi_pci_run_osc(root->device->handle, capbuf, &result); 238 286 if (ACPI_SUCCESS(status)) { ··· 379 427 if (ACPI_FAILURE(status)) 380 428 return status; 381 429 382 - control_req = (flags & OSC_CONTROL_MASKS); 430 + control_req = (flags & OSC_PCI_CONTROL_MASKS); 383 431 if (!control_req) 384 432 return AE_TYPE; 385 433
+5 -5
drivers/acpi/processor_core.c
··· 353 353 PDE(inode)->data); 354 354 } 355 355 356 - static int acpi_processor_add_fs(struct acpi_device *device) 356 + static int __cpuinit acpi_processor_add_fs(struct acpi_device *device) 357 357 { 358 358 struct proc_dir_entry *entry = NULL; 359 359 ··· 722 722 switch (event) { 723 723 case ACPI_PROCESSOR_NOTIFY_PERFORMANCE: 724 724 saved = pr->performance_platform_limit; 725 - acpi_processor_ppc_has_changed(pr); 725 + acpi_processor_ppc_has_changed(pr, 1); 726 726 if (saved == pr->performance_platform_limit) 727 727 break; 728 728 acpi_bus_generate_proc_event(device, event, ··· 758 758 struct acpi_processor *pr = per_cpu(processors, cpu); 759 759 760 760 if (action == CPU_ONLINE && pr) { 761 - acpi_processor_ppc_has_changed(pr); 761 + acpi_processor_ppc_has_changed(pr, 0); 762 762 acpi_processor_cst_has_changed(pr); 763 763 acpi_processor_tstate_has_changed(pr); 764 764 } ··· 830 830 arch_acpi_processor_cleanup_pdc(pr); 831 831 832 832 #ifdef CONFIG_CPU_FREQ 833 - acpi_processor_ppc_has_changed(pr); 833 + acpi_processor_ppc_has_changed(pr, 0); 834 834 #endif 835 835 acpi_processor_get_throttling_info(pr); 836 836 acpi_processor_get_limit_info(pr); ··· 845 845 goto err_power_exit; 846 846 } 847 847 848 - dev_info(&device->dev, "registered as cooling_device%d\n", 848 + dev_dbg(&device->dev, "registered as cooling_device%d\n", 849 849 pr->cdev->id); 850 850 851 851 result = sysfs_create_link(&device->dev.kobj,
+8 -3
drivers/acpi/processor_idle.c
··· 164 164 pr->power.timer_broadcast_on_state = state; 165 165 } 166 166 167 - static void lapic_timer_propagate_broadcast(void *arg) 167 + static void __lapic_timer_propagate_broadcast(void *arg) 168 168 { 169 169 struct acpi_processor *pr = (struct acpi_processor *) arg; 170 170 unsigned long reason; ··· 173 173 CLOCK_EVT_NOTIFY_BROADCAST_ON : CLOCK_EVT_NOTIFY_BROADCAST_OFF; 174 174 175 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); 176 182 } 177 183 178 184 /* Power(C) State timer broadcast control */ ··· 644 638 working++; 645 639 } 646 640 647 - smp_call_function_single(pr->id, lapic_timer_propagate_broadcast, 648 - pr, 1); 641 + lapic_timer_propagate_broadcast(pr); 649 642 650 643 return (working); 651 644 }
+47 -3
drivers/acpi/processor_perflib.c
··· 152 152 return 0; 153 153 } 154 154 155 - int acpi_processor_ppc_has_changed(struct acpi_processor *pr) 155 + #define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80 156 + /* 157 + * acpi_processor_ppc_ost: Notify firmware the _PPC evaluation status 158 + * @handle: ACPI processor handle 159 + * @status: the status code of _PPC evaluation 160 + * 0: success. OSPM is now using the performance state specificed. 161 + * 1: failure. OSPM has not changed the number of P-states in use 162 + */ 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) 156 184 { 157 185 int ret; 158 186 159 - if (ignore_ppc) 187 + if (ignore_ppc) { 188 + /* 189 + * Only when it is notification event, the _OST object 190 + * will be evaluated. Otherwise it is skipped. 191 + */ 192 + if (event_flag) 193 + acpi_processor_ppc_ost(pr->handle, 1); 160 194 return 0; 195 + } 161 196 162 197 ret = acpi_processor_get_platform_limit(pr); 163 - 198 + /* 199 + * Only when it is notification event, the _OST object 200 + * will be evaluated. Otherwise it is skipped. 201 + */ 202 + if (event_flag) { 203 + if (ret < 0) 204 + acpi_processor_ppc_ost(pr->handle, 1); 205 + else 206 + acpi_processor_ppc_ost(pr->handle, 0); 207 + } 164 208 if (ret < 0) 165 209 return (ret); 166 210 else
+7
drivers/acpi/thermal.c
··· 1052 1052 acpi_device_bid(device)); 1053 1053 } 1054 1054 seq_puts(seq, "\n"); 1055 + } else { 1056 + seq_printf(seq, "passive (forced):"); 1057 + if (tz->thermal_zone->forced_passive) 1058 + seq_printf(seq, " %i C\n", 1059 + tz->thermal_zone->forced_passive / 1000); 1060 + else 1061 + seq_printf(seq, "<not set>\n"); 1055 1062 } 1056 1063 1057 1064 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
+109 -9
drivers/char/ipmi/ipmi_si_intf.c
··· 64 64 #include <linux/dmi.h> 65 65 #include <linux/string.h> 66 66 #include <linux/ctype.h> 67 + #include <linux/pnp.h> 67 68 68 69 #ifdef CONFIG_PPC_OF 69 70 #include <linux/of_device.h> ··· 1920 1919 s8 spmi_id[1]; /* A '\0' terminated array starts here. */ 1921 1920 }; 1922 1921 1923 - static __devinit int try_init_acpi(struct SPMITable *spmi) 1922 + static __devinit int try_init_spmi(struct SPMITable *spmi) 1924 1923 { 1925 1924 struct smi_info *info; 1926 1925 u8 addr_space; ··· 1941 1940 return -ENOMEM; 1942 1941 } 1943 1942 1944 - info->addr_source = "ACPI"; 1943 + info->addr_source = "SPMI"; 1945 1944 1946 1945 /* Figure out the interface type. */ 1947 1946 switch (spmi->InterfaceType) { ··· 2003 2002 return 0; 2004 2003 } 2005 2004 2006 - static __devinit void acpi_find_bmc(void) 2005 + static __devinit void spmi_find_bmc(void) 2007 2006 { 2008 2007 acpi_status status; 2009 2008 struct SPMITable *spmi; ··· 2021 2020 if (status != AE_OK) 2022 2021 return; 2023 2022 2024 - try_init_acpi(spmi); 2023 + try_init_spmi(spmi); 2025 2024 } 2026 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 + }; 2027 2123 #endif 2028 2124 2029 2125 #ifdef CONFIG_DMI ··· 2300 2202 int rv; 2301 2203 int class_type = pdev->class & PCI_ERMC_CLASSCODE_TYPE_MASK; 2302 2204 struct smi_info *info; 2303 - int first_reg_offset = 0; 2304 2205 2305 2206 info = kzalloc(sizeof(*info), GFP_KERNEL); 2306 2207 if (!info) ··· 2337 2240 2338 2241 info->addr_source_cleanup = ipmi_pci_cleanup; 2339 2242 info->addr_source_data = pdev; 2340 - 2341 - if (pdev->subsystem_vendor == PCI_HP_VENDOR_ID) 2342 - first_reg_offset = 1; 2343 2243 2344 2244 if (pci_resource_flags(pdev, 0) & IORESOURCE_IO) { 2345 2245 info->io_setup = port_setup; ··· 3202 3108 #endif 3203 3109 3204 3110 #ifdef CONFIG_ACPI 3205 - acpi_find_bmc(); 3111 + spmi_find_bmc(); 3112 + #endif 3113 + #ifdef CONFIG_PNP 3114 + pnp_register_driver(&ipmi_pnp_driver); 3206 3115 #endif 3207 3116 3208 3117 #ifdef CONFIG_PCI ··· 3329 3232 3330 3233 #ifdef CONFIG_PCI 3331 3234 pci_unregister_driver(&ipmi_pci_driver); 3235 + #endif 3236 + #ifdef CONFIG_PNP 3237 + pnp_unregister_driver(&ipmi_pnp_driver); 3332 3238 #endif 3333 3239 3334 3240 #ifdef CONFIG_PPC_OF
-13
drivers/misc/Kconfig
··· 248 248 This option enables addition debugging code for the SGI GRU driver. If 249 249 you are unsure, say N. 250 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 251 config ISL29003 265 252 tristate "Intersil ISL29003 ambient light sensor" 266 253 depends on I2C && SYSFS
+29
drivers/platform/x86/Kconfig
··· 334 334 depends on HOTPLUG_PCI 335 335 select BACKLIGHT_CLASS_DEVICE 336 336 select HWMON 337 + select LEDS_CLASS 338 + select NEW_LEDS 337 339 ---help--- 338 340 This driver supports the Fn-Fx keys on Eee PC laptops. 339 341 ··· 366 364 367 365 It is safe to enable this driver even if your DSDT doesn't define 368 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. 369 379 370 380 config ACPI_ASUS 371 381 tristate "ASUS/Medion Laptop Extras (DEPRECATED)" ··· 449 435 450 436 If you have a legacy free Toshiba laptop (such as the Libretto L1 451 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. 452 453 endif # X86_PLATFORM_DEVICES
+2
drivers/platform/x86/Makefile
··· 18 18 obj-$(CONFIG_PANASONIC_LAPTOP) += panasonic-laptop.o 19 19 obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o 20 20 obj-$(CONFIG_ACPI_WMI) += wmi.o 21 + obj-$(CONFIG_MSI_WMI) += msi-wmi.o 21 22 obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o 22 23 obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o 23 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 52 */ 53 53 #undef START_IN_KERNEL_MODE 54 54 55 - #define DRV_VER "0.5.18" 55 + #define DRV_VER "0.5.20" 56 56 57 57 /* 58 58 * According to the Atom N270 datasheet, ··· 112 112 MODULE_PARM_DESC(force_product, "Force BIOS product and omit BIOS check"); 113 113 114 114 /* 115 - * cmd_off: to switch the fan completely off / to check if the fan is off 115 + * cmd_off: to switch the fan completely off 116 + * chk_off: to check if the fan is off 116 117 * cmd_auto: to set the BIOS in control of the fan. The BIOS regulates then 117 118 * the fan speed depending on the temperature 118 119 */ 119 120 struct fancmd { 120 121 u8 cmd_off; 122 + u8 chk_off; 121 123 u8 cmd_auto; 122 124 }; 123 125 ··· 136 134 /* Register addresses and values for different BIOS versions */ 137 135 static const struct bios_settings_t bios_tbl[] = { 138 136 /* 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} }, 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} }, 148 146 /* 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} }, 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 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} }, 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} }, 163 170 /* pewpew-terminator */ 164 - {"", "", "", 0, 0, {0, 0} } 171 + {"", "", "", 0, 0, {0, 0, 0} } 165 172 }; 166 173 167 174 static const struct bios_settings_t *bios_cfg __read_mostly; ··· 194 183 if (ec_read(bios_cfg->fanreg, &fan)) 195 184 return -EINVAL; 196 185 197 - if (fan != bios_cfg->cmd.cmd_off) 186 + if (fan != bios_cfg->cmd.chk_off) 198 187 *state = ACERHDF_FAN_AUTO; 199 188 else 200 189 *state = ACERHDF_FAN_OFF;
+13 -12
drivers/platform/x86/asus-laptop.c
··· 221 221 */ 222 222 static const struct acpi_device_id asus_device_ids[] = { 223 223 {"ATK0100", 0}, 224 + {"ATK0101", 0}, 224 225 {"", 0}, 225 226 }; 226 227 MODULE_DEVICE_TABLE(acpi, asus_device_ids); ··· 233 232 static struct acpi_driver asus_hotk_driver = { 234 233 .name = ASUS_HOTK_NAME, 235 234 .class = ASUS_HOTK_CLASS, 235 + .owner = THIS_MODULE, 236 236 .ids = asus_device_ids, 237 237 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, 238 238 .ops = { ··· 295 293 enum { KE_KEY, KE_END }; 296 294 297 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}, 298 301 {KE_KEY, 0x30, KEY_VOLUMEUP}, 299 302 {KE_KEY, 0x31, KEY_VOLUMEDOWN}, 300 303 {KE_KEY, 0x32, KEY_MUTE}, ··· 319 312 {KE_KEY, 0x5F, KEY_WLAN}, 320 313 {KE_KEY, 0x60, KEY_SWITCHVIDEOMODE}, 321 314 {KE_KEY, 0x61, KEY_SWITCHVIDEOMODE}, 322 - {KE_KEY, 0x6B, BTN_TOUCH}, /* Lock Mouse */ 315 + {KE_KEY, 0x62, KEY_SWITCHVIDEOMODE}, 316 + {KE_KEY, 0x63, KEY_SWITCHVIDEOMODE}, 317 + {KE_KEY, 0x6B, KEY_F13}, /* Lock Touchpad */ 323 318 {KE_KEY, 0x82, KEY_CAMERA}, 319 + {KE_KEY, 0x88, KEY_WLAN }, 324 320 {KE_KEY, 0x8A, KEY_PROG1}, 325 321 {KE_KEY, 0x95, KEY_MEDIA}, 326 322 {KE_KEY, 0x99, KEY_PHONE}, ··· 1250 1240 { 1251 1241 int result; 1252 1242 1253 - if (!device) 1254 - return -EINVAL; 1255 - 1256 1243 pr_notice("Asus Laptop Support version %s\n", 1257 1244 ASUS_LAPTOP_VERSION); 1258 1245 ··· 1290 1283 hotk->ledd_status = 0xFFF; 1291 1284 1292 1285 /* 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 */ 1286 + hotk->light_switch = 0; /* Default to light sensor disabled */ 1287 + hotk->light_level = 5; /* level 5 for sensor sensitivity */ 1295 1288 1296 1289 if (ls_switch_handle) 1297 1290 set_light_sens_switch(hotk->light_switch); ··· 1313 1306 1314 1307 static int asus_hotk_remove(struct acpi_device *device, int type) 1315 1308 { 1316 - if (!device || !acpi_driver_data(device)) 1317 - return -EINVAL; 1318 - 1319 1309 kfree(hotk->name); 1320 1310 kfree(hotk); 1321 1311 ··· 1447 1443 static int __init asus_laptop_init(void) 1448 1444 { 1449 1445 int result; 1450 - 1451 - if (acpi_disabled) 1452 - return -ENODEV; 1453 1446 1454 1447 result = acpi_bus_register_driver(&asus_hotk_driver); 1455 1448 if (result < 0)
+5 -14
drivers/platform/x86/asus_acpi.c
··· 466 466 static struct acpi_driver asus_hotk_driver = { 467 467 .name = "asus_acpi", 468 468 .class = ACPI_HOTK_CLASS, 469 + .owner = THIS_MODULE, 469 470 .ids = asus_device_ids, 470 471 .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS, 471 472 .ops = { ··· 1335 1334 acpi_status status = AE_OK; 1336 1335 int result; 1337 1336 1338 - if (!device) 1339 - return -EINVAL; 1340 - 1341 1337 printk(KERN_NOTICE "Asus Laptop ACPI Extras version %s\n", 1342 1338 ASUS_ACPI_VERSION); 1343 1339 ··· 1390 1392 1391 1393 static int asus_hotk_remove(struct acpi_device *device, int type) 1392 1394 { 1393 - if (!device || !acpi_driver_data(device)) 1394 - return -EINVAL; 1395 - 1396 1395 asus_hotk_remove_fs(device); 1397 1396 1398 1397 kfree(hotk); ··· 1417 1422 { 1418 1423 int result; 1419 1424 1420 - if (acpi_disabled) 1421 - return -ENODEV; 1425 + result = acpi_bus_register_driver(&asus_hotk_driver); 1426 + if (result < 0) 1427 + return result; 1422 1428 1423 1429 asus_proc_dir = proc_mkdir(PROC_ASUS, acpi_root_dir); 1424 1430 if (!asus_proc_dir) { 1425 1431 printk(KERN_ERR "Asus ACPI: Unable to create /proc entry\n"); 1432 + acpi_bus_unregister_driver(&asus_hotk_driver); 1426 1433 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 } 1434 1435 1435 1436 /*
+62 -24
drivers/platform/x86/dell-laptop.c
··· 58 58 static int da_num_tokens; 59 59 static struct calling_interface_token *da_tokens; 60 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; 61 69 static struct backlight_device *dell_backlight_device; 62 70 static struct rfkill *wifi_rfkill; 63 71 static struct rfkill *bluetooth_rfkill; ··· 82 74 { } 83 75 }; 84 76 85 - static void parse_da_table(const struct dmi_header *dm) 77 + static void __init parse_da_table(const struct dmi_header *dm) 86 78 { 87 79 /* Final token is a terminator, so we don't want to copy it */ 88 80 int tokens = (dm->length-11)/sizeof(struct calling_interface_token)-1; ··· 111 103 da_num_tokens += tokens; 112 104 } 113 105 114 - static void find_tokens(const struct dmi_header *dm, void *dummy) 106 + static void __init find_tokens(const struct dmi_header *dm, void *dummy) 115 107 { 116 108 switch (dm->type) { 117 109 case 0xd4: /* Indexed IO */ ··· 205 197 dell_send_request(&buffer, 17, 11); 206 198 status = buffer.output[1]; 207 199 208 - if (status & BIT(bit)) 209 - rfkill_set_hw_state(rfkill, !!(status & BIT(16))); 200 + rfkill_set_sw_state(rfkill, !!(status & BIT(bit))); 201 + rfkill_set_hw_state(rfkill, !(status & BIT(16))); 210 202 } 211 203 212 204 static const struct rfkill_ops dell_rfkill_ops = { ··· 214 206 .query = dell_rfkill_query, 215 207 }; 216 208 217 - static int dell_setup_rfkill(void) 209 + static int __init dell_setup_rfkill(void) 218 210 { 219 211 struct calling_interface_buffer buffer; 220 212 int status; ··· 225 217 status = buffer.output[1]; 226 218 227 219 if ((status & (1<<2|1<<8)) == (1<<2|1<<8)) { 228 - wifi_rfkill = rfkill_alloc("dell-wifi", NULL, RFKILL_TYPE_WLAN, 220 + wifi_rfkill = rfkill_alloc("dell-wifi", &platform_device->dev, 221 + RFKILL_TYPE_WLAN, 229 222 &dell_rfkill_ops, (void *) 1); 230 223 if (!wifi_rfkill) { 231 224 ret = -ENOMEM; ··· 238 229 } 239 230 240 231 if ((status & (1<<3|1<<9)) == (1<<3|1<<9)) { 241 - bluetooth_rfkill = rfkill_alloc("dell-bluetooth", NULL, 232 + bluetooth_rfkill = rfkill_alloc("dell-bluetooth", 233 + &platform_device->dev, 242 234 RFKILL_TYPE_BLUETOOTH, 243 235 &dell_rfkill_ops, (void *) 2); 244 236 if (!bluetooth_rfkill) { ··· 252 242 } 253 243 254 244 if ((status & (1<<4|1<<10)) == (1<<4|1<<10)) { 255 - wwan_rfkill = rfkill_alloc("dell-wwan", NULL, RFKILL_TYPE_WWAN, 245 + wwan_rfkill = rfkill_alloc("dell-wwan", 246 + &platform_device->dev, 247 + RFKILL_TYPE_WWAN, 256 248 &dell_rfkill_ops, (void *) 3); 257 249 if (!wwan_rfkill) { 258 250 ret = -ENOMEM; ··· 278 266 rfkill_destroy(wifi_rfkill); 279 267 280 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 + } 281 285 } 282 286 283 287 static int dell_send_intensity(struct backlight_device *bd) ··· 354 326 return -ENODEV; 355 327 } 356 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 + 357 341 ret = dell_setup_rfkill(); 358 342 359 343 if (ret) { 360 344 printk(KERN_WARNING "dell-laptop: Unable to setup rfkill\n"); 361 - goto out; 345 + goto fail_rfkill; 362 346 } 363 347 364 348 #ifdef CONFIG_ACPI ··· 392 352 if (max_intensity) { 393 353 dell_backlight_device = backlight_device_register( 394 354 "dell_backlight", 395 - NULL, NULL, 355 + &platform_device->dev, NULL, 396 356 &dell_ops); 397 357 398 358 if (IS_ERR(dell_backlight_device)) { 399 359 ret = PTR_ERR(dell_backlight_device); 400 360 dell_backlight_device = NULL; 401 - goto out; 361 + goto fail_backlight; 402 362 } 403 363 404 364 dell_backlight_device->props.max_brightness = max_intensity; ··· 408 368 } 409 369 410 370 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); 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: 418 381 kfree(da_tokens); 419 382 return ret; 420 383 } ··· 425 382 static void __exit dell_exit(void) 426 383 { 427 384 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); 385 + dell_cleanup_rfkill(); 434 386 } 435 387 436 388 module_init(dell_init);
+116 -13
drivers/platform/x86/dell-wmi.c
··· 31 31 #include <acpi/acpi_drivers.h> 32 32 #include <linux/acpi.h> 33 33 #include <linux/string.h> 34 + #include <linux/dmi.h> 34 35 35 36 MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>"); 36 37 MODULE_DESCRIPTION("Dell laptop WMI hotkeys driver"); 37 38 MODULE_LICENSE("GPL"); 38 39 39 40 #define DELL_EVENT_GUID "9DBB5994-A997-11DA-B012-B622A1EF5492" 41 + 42 + static int acpi_video; 40 43 41 44 MODULE_ALIAS("wmi:"DELL_EVENT_GUID); 42 45 ··· 57 54 * via the keyboard controller so should not be sent again. 58 55 */ 59 56 60 - static struct key_entry dell_wmi_keymap[] = { 57 + static struct key_entry dell_legacy_wmi_keymap[] = { 61 58 {KE_KEY, 0xe045, KEY_PROG1}, 62 59 {KE_KEY, 0xe009, KEY_EJECTCD}, 63 60 ··· 75 72 76 73 /* The next device is at offset 6, the active devices are at 77 74 offset 8 and the attached devices at offset 10 */ 78 - {KE_KEY, 0xe00b, KEY_DISPLAYTOGGLE}, 75 + {KE_KEY, 0xe00b, KEY_SWITCHVIDEOMODE}, 79 76 80 77 {KE_IGNORE, 0xe00c, KEY_KBDILLUMTOGGLE}, 81 78 ··· 98 95 {KE_IGNORE, 0xe046, KEY_SCROLLLOCK}, 99 96 {KE_END, 0} 100 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; 101 139 102 140 static struct input_dev *dell_wmi_input_dev; 103 141 ··· 208 164 obj = (union acpi_object *)response.pointer; 209 165 210 166 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) { 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 { 219 191 input_report_key(dell_wmi_input_dev, key->keycode, 1); 220 192 input_sync(dell_wmi_input_dev); 221 193 input_report_key(dell_wmi_input_dev, key->keycode, 0); 222 194 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); 195 + } 226 196 } 227 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 + 228 238 229 239 static int __init dell_wmi_input_setup(void) 230 240 { ··· 324 226 int err; 325 227 326 228 if (wmi_has_guid(DELL_EVENT_GUID)) { 229 + 230 + dmi_walk(find_hk_type, NULL); 231 + 327 232 err = dell_wmi_input_setup(); 328 233 329 234 if (err) ··· 340 239 " notify handler - %d\n", err); 341 240 return err; 342 241 } 242 + 243 + acpi_video = acpi_video_backlight_support(); 343 244 344 245 } else 345 246 printk(KERN_WARNING "dell-wmi: No known WMI GUID found\n");
+831 -674
drivers/platform/x86/eeepc-laptop.c
··· 1 1 /* 2 - * eepc-laptop.c - Asus Eee PC extras 2 + * eeepc-laptop.c - Asus Eee PC extras 3 3 * 4 4 * Based on asus_acpi.c as patched for the Eee PC by Asus: 5 5 * ftp://ftp.asus.com/pub/ASUS/EeePC/701/ASUS_ACPI_071126.rar ··· 34 34 #include <linux/rfkill.h> 35 35 #include <linux/pci.h> 36 36 #include <linux/pci_hotplug.h> 37 + #include <linux/leds.h> 37 38 38 39 #define EEEPC_LAPTOP_VERSION "0.1" 40 + #define EEEPC_LAPTOP_NAME "Eee PC Hotkey Driver" 41 + #define EEEPC_LAPTOP_FILE "eeepc" 39 42 40 - #define EEEPC_HOTK_NAME "Eee PC Hotkey Driver" 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" 43 + #define EEEPC_ACPI_CLASS "hotkey" 44 + #define EEEPC_ACPI_DEVICE_NAME "Hotkey" 45 + #define EEEPC_ACPI_HID "ASUS010" 45 46 47 + MODULE_AUTHOR("Corentin Chary, Eric Cooper"); 48 + MODULE_DESCRIPTION(EEEPC_LAPTOP_NAME); 49 + MODULE_LICENSE("GPL"); 46 50 47 51 /* 48 52 * Definitions for Asus EeePC 49 53 */ 50 - #define NOTIFY_WLAN_ON 0x10 51 54 #define NOTIFY_BRN_MIN 0x20 52 55 #define NOTIFY_BRN_MAX 0x2f 53 56 ··· 120 117 NULL, NULL, "PBPS", "TPDS" 121 118 }; 122 119 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 120 struct key_entry { 176 121 char type; 177 122 u8 code; ··· 128 177 129 178 enum { KE_KEY, KE_END }; 130 179 131 - static struct key_entry eeepc_keymap[] = { 180 + static const struct key_entry eeepc_keymap[] = { 132 181 /* Sleep already handled via generic ACPI code */ 133 182 {KE_KEY, 0x10, KEY_WLAN }, 134 183 {KE_KEY, 0x11, KEY_WLAN }, ··· 136 185 {KE_KEY, 0x13, KEY_MUTE }, 137 186 {KE_KEY, 0x14, KEY_VOLUMEDOWN }, 138 187 {KE_KEY, 0x15, KEY_VOLUMEUP }, 188 + {KE_KEY, 0x16, KEY_DISPLAY_OFF }, 139 189 {KE_KEY, 0x1a, KEY_COFFEE }, 140 190 {KE_KEY, 0x1b, KEY_ZOOM }, 141 191 {KE_KEY, 0x1c, KEY_PROG2 }, 142 192 {KE_KEY, 0x1d, KEY_PROG3 }, 143 - {KE_KEY, NOTIFY_BRN_MIN, KEY_BRIGHTNESSDOWN }, 144 - {KE_KEY, NOTIFY_BRN_MIN + 2, KEY_BRIGHTNESSUP }, 193 + {KE_KEY, NOTIFY_BRN_MIN, KEY_BRIGHTNESSDOWN }, 194 + {KE_KEY, NOTIFY_BRN_MAX, KEY_BRIGHTNESSUP }, 145 195 {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE }, 146 196 {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE }, 147 197 {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE }, 198 + {KE_KEY, 0x37, KEY_F13 }, /* Disable Touchpad */ 199 + {KE_KEY, 0x38, KEY_F14 }, 148 200 {KE_END, 0}, 149 201 }; 150 202 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 203 191 204 /* 192 - * The backlight class declaration 205 + * This is the main structure, we can use it to store useful information 193 206 */ 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 - }; 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 */ 200 212 201 - MODULE_AUTHOR("Corentin Chary, Eric Cooper"); 202 - MODULE_DESCRIPTION(EEEPC_HOTK_NAME); 203 - MODULE_LICENSE("GPL"); 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 + }; 204 233 205 234 /* 206 235 * ACPI Helpers 207 236 */ 208 - static int write_acpi_int(acpi_handle handle, const char *method, int val, 209 - struct acpi_buffer *output) 237 + static int write_acpi_int(acpi_handle handle, const char *method, int val) 210 238 { 211 239 struct acpi_object_list params; 212 240 union acpi_object in_obj; ··· 196 266 in_obj.type = ACPI_TYPE_INTEGER; 197 267 in_obj.integer.value = val; 198 268 199 - status = acpi_evaluate_object(handle, (char *)method, &params, output); 269 + status = acpi_evaluate_object(handle, (char *)method, &params, NULL); 200 270 return (status == AE_OK ? 0 : -1); 201 271 } 202 272 ··· 215 285 } 216 286 } 217 287 218 - static int set_acpi(int cm, int value) 288 + static int set_acpi(struct eeepc_laptop *eeepc, int cm, int value) 219 289 { 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); 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; 226 333 } 227 334 return 0; 228 335 } 229 336 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 337 293 338 /* 294 339 * Sys helpers ··· 277 372 return count; 278 373 } 279 374 280 - static ssize_t store_sys_acpi(int cm, const char *buf, size_t count) 375 + static ssize_t store_sys_acpi(struct device *dev, int cm, 376 + const char *buf, size_t count) 281 377 { 378 + struct eeepc_laptop *eeepc = dev_get_drvdata(dev); 282 379 int rv, value; 283 380 284 381 rv = parse_arg(buf, count, &value); 285 382 if (rv > 0) 286 - value = set_acpi(cm, value); 383 + value = set_acpi(eeepc, cm, value); 287 384 if (value < 0) 288 - return value; 385 + return -EIO; 289 386 return rv; 290 387 } 291 388 292 - static ssize_t show_sys_acpi(int cm, char *buf) 389 + static ssize_t show_sys_acpi(struct device *dev, int cm, char *buf) 293 390 { 294 - int value = get_acpi(cm); 391 + struct eeepc_laptop *eeepc = dev_get_drvdata(dev); 392 + int value = get_acpi(eeepc, cm); 295 393 296 394 if (value < 0) 297 - return value; 395 + return -EIO; 298 396 return sprintf(buf, "%d\n", value); 299 397 } 300 398 301 - #define EEEPC_CREATE_DEVICE_ATTR(_name, _cm) \ 399 + #define EEEPC_CREATE_DEVICE_ATTR(_name, _mode, _cm) \ 302 400 static ssize_t show_##_name(struct device *dev, \ 303 401 struct device_attribute *attr, \ 304 402 char *buf) \ 305 403 { \ 306 - return show_sys_acpi(_cm, buf); \ 404 + return show_sys_acpi(dev, _cm, buf); \ 307 405 } \ 308 406 static ssize_t store_##_name(struct device *dev, \ 309 407 struct device_attribute *attr, \ 310 408 const char *buf, size_t count) \ 311 409 { \ 312 - return store_sys_acpi(_cm, buf, count); \ 410 + return store_sys_acpi(dev, _cm, buf, count); \ 313 411 } \ 314 412 static struct device_attribute dev_attr_##_name = { \ 315 413 .attr = { \ 316 414 .name = __stringify(_name), \ 317 - .mode = 0644 }, \ 415 + .mode = _mode }, \ 318 416 .show = show_##_name, \ 319 417 .store = store_##_name, \ 320 418 } 321 419 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); 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); 325 423 326 424 struct eeepc_cpufv { 327 425 int num; 328 426 int cur; 329 427 }; 330 428 331 - static int get_cpufv(struct eeepc_cpufv *c) 429 + static int get_cpufv(struct eeepc_laptop *eeepc, struct eeepc_cpufv *c) 332 430 { 333 - c->cur = get_acpi(CM_ASL_CPUFV); 431 + c->cur = get_acpi(eeepc, CM_ASL_CPUFV); 334 432 c->num = (c->cur >> 8) & 0xff; 335 433 c->cur &= 0xff; 336 434 if (c->cur < 0 || c->num <= 0 || c->num > 12) ··· 345 437 struct device_attribute *attr, 346 438 char *buf) 347 439 { 440 + struct eeepc_laptop *eeepc = dev_get_drvdata(dev); 348 441 struct eeepc_cpufv c; 349 442 int i; 350 443 ssize_t len = 0; 351 444 352 - if (get_cpufv(&c)) 445 + if (get_cpufv(eeepc, &c)) 353 446 return -ENODEV; 354 447 for (i = 0; i < c.num; i++) 355 448 len += sprintf(buf + len, "%d ", i); ··· 362 453 struct device_attribute *attr, 363 454 char *buf) 364 455 { 456 + struct eeepc_laptop *eeepc = dev_get_drvdata(dev); 365 457 struct eeepc_cpufv c; 366 458 367 - if (get_cpufv(&c)) 459 + if (get_cpufv(eeepc, &c)) 368 460 return -ENODEV; 369 461 return sprintf(buf, "%#x\n", (c.num << 8) | c.cur); 370 462 } ··· 374 464 struct device_attribute *attr, 375 465 const char *buf, size_t count) 376 466 { 467 + struct eeepc_laptop *eeepc = dev_get_drvdata(dev); 377 468 struct eeepc_cpufv c; 378 469 int rv, value; 379 470 380 - if (get_cpufv(&c)) 471 + if (get_cpufv(eeepc, &c)) 381 472 return -ENODEV; 382 473 rv = parse_arg(buf, count, &value); 383 474 if (rv < 0) 384 475 return rv; 385 476 if (!rv || value < 0 || value >= c.num) 386 477 return -EINVAL; 387 - set_acpi(CM_ASL_CPUFV, value); 478 + set_acpi(eeepc, CM_ASL_CPUFV, value); 388 479 return rv; 389 480 } 390 481 ··· 417 506 .attrs = platform_attributes 418 507 }; 419 508 420 - /* 421 - * Hotkey functions 422 - */ 423 - static struct key_entry *eepc_get_entry_by_scancode(int code) 509 + static int eeepc_platform_init(struct eeepc_laptop *eeepc) 424 510 { 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 511 int result; 504 512 505 - result = acpi_bus_get_status(ehotk->device); 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); 506 519 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; 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; 529 592 } 593 + 530 594 return 0; 531 595 } 532 596 533 - static int notify_brn(void) 597 + static void eeepc_led_exit(struct eeepc_laptop *eeepc) 534 598 { 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; 599 + if (eeepc->tpd_led.dev) 600 + led_classdev_unregister(&eeepc->tpd_led); 601 + if (eeepc->led_workqueue) 602 + destroy_workqueue(eeepc->led_workqueue); 543 603 } 544 604 545 - static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot, 546 - u8 *value) 605 + 606 + /* 607 + * PCI hotplug (for wlan rfkill) 608 + */ 609 + static bool eeepc_wlan_rfkill_blocked(struct eeepc_laptop *eeepc) 547 610 { 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; 611 + if (get_acpi(eeepc, CM_ASL_WLAN) == 1) 612 + return false; 613 + return true; 556 614 } 557 615 558 - static void eeepc_rfkill_hotplug(void) 616 + static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc) 559 617 { 560 618 struct pci_dev *dev; 561 619 struct pci_bus *bus; 562 - bool blocked = eeepc_wlan_rfkill_blocked(); 620 + bool blocked = eeepc_wlan_rfkill_blocked(eeepc); 563 621 564 - if (ehotk->wlan_rfkill) 565 - rfkill_set_sw_state(ehotk->wlan_rfkill, blocked); 622 + if (eeepc->wlan_rfkill) 623 + rfkill_set_sw_state(eeepc->wlan_rfkill, blocked); 566 624 567 - mutex_lock(&ehotk->hotplug_lock); 625 + mutex_lock(&eeepc->hotplug_lock); 568 626 569 - if (ehotk->hotplug_slot) { 627 + if (eeepc->hotplug_slot) { 570 628 bus = pci_find_bus(0, 1); 571 629 if (!bus) { 572 630 pr_warning("Unable to find PCI bus 1?\n"); ··· 565 685 } 566 686 567 687 out_unlock: 568 - mutex_unlock(&ehotk->hotplug_lock); 688 + mutex_unlock(&eeepc->hotplug_lock); 569 689 } 570 690 571 691 static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) 572 692 { 693 + struct eeepc_laptop *eeepc = data; 694 + 573 695 if (event != ACPI_NOTIFY_BUS_CHECK) 574 696 return; 575 697 576 - eeepc_rfkill_hotplug(); 698 + eeepc_rfkill_hotplug(eeepc); 577 699 } 578 700 579 - static void eeepc_hotk_notify(struct acpi_device *device, u32 event) 701 + static int eeepc_register_rfkill_notifier(struct eeepc_laptop *eeepc, 702 + char *node) 580 703 { 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; 704 + acpi_status status; 631 705 acpi_handle handle; 632 706 633 707 status = acpi_get_handle(NULL, node, &handle); ··· 590 756 status = acpi_install_notify_handler(handle, 591 757 ACPI_SYSTEM_NOTIFY, 592 758 eeepc_rfkill_notify, 593 - NULL); 759 + eeepc); 594 760 if (ACPI_FAILURE(status)) 595 761 pr_warning("Failed to register notify on %s\n", node); 596 762 } else ··· 599 765 return 0; 600 766 } 601 767 602 - static void eeepc_unregister_rfkill_notifier(char *node) 768 + static void eeepc_unregister_rfkill_notifier(struct eeepc_laptop *eeepc, 769 + char *node) 603 770 { 604 771 acpi_status status = AE_OK; 605 772 acpi_handle handle; ··· 617 782 } 618 783 } 619 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 + 620 799 static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot) 621 800 { 622 801 kfree(hotplug_slot->info); 623 802 kfree(hotplug_slot); 624 803 } 625 804 626 - static int eeepc_setup_pci_hotplug(void) 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) 627 812 { 628 813 int ret = -ENOMEM; 629 814 struct pci_bus *bus = pci_find_bus(0, 1); ··· 653 798 return -ENODEV; 654 799 } 655 800 656 - ehotk->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL); 657 - if (!ehotk->hotplug_slot) 801 + eeepc->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL); 802 + if (!eeepc->hotplug_slot) 658 803 goto error_slot; 659 804 660 - ehotk->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info), 805 + eeepc->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info), 661 806 GFP_KERNEL); 662 - if (!ehotk->hotplug_slot->info) 807 + if (!eeepc->hotplug_slot->info) 663 808 goto error_info; 664 809 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); 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); 670 815 671 - ret = pci_hp_register(ehotk->hotplug_slot, bus, 0, "eeepc-wifi"); 816 + ret = pci_hp_register(eeepc->hotplug_slot, bus, 0, "eeepc-wifi"); 672 817 if (ret) { 673 818 pr_err("Unable to register hotplug slot - %d\n", ret); 674 819 goto error_register; ··· 677 822 return 0; 678 823 679 824 error_register: 680 - kfree(ehotk->hotplug_slot->info); 825 + kfree(eeepc->hotplug_slot->info); 681 826 error_info: 682 - kfree(ehotk->hotplug_slot); 683 - ehotk->hotplug_slot = NULL; 827 + kfree(eeepc->hotplug_slot); 828 + eeepc->hotplug_slot = NULL; 684 829 error_slot: 685 830 return ret; 686 831 } 687 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 + */ 688 970 static int eeepc_hotk_thaw(struct device *device) 689 971 { 690 - if (ehotk->wlan_rfkill) { 972 + struct eeepc_laptop *eeepc = dev_get_drvdata(device); 973 + 974 + if (eeepc->wlan_rfkill) { 691 975 bool wlan; 692 976 693 977 /* ··· 834 840 * during suspend. Normally it restores it on resume, but 835 841 * we should kick it ourselves in case hibernation is aborted. 836 842 */ 837 - wlan = get_acpi(CM_ASL_WLAN); 838 - set_acpi(CM_ASL_WLAN, wlan); 843 + wlan = get_acpi(eeepc, CM_ASL_WLAN); 844 + set_acpi(eeepc, CM_ASL_WLAN, wlan); 839 845 } 840 846 841 847 return 0; ··· 843 849 844 850 static int eeepc_hotk_restore(struct device *device) 845 851 { 846 - /* Refresh both wlan rfkill state and pci hotplug */ 847 - if (ehotk->wlan_rfkill) 848 - eeepc_rfkill_hotplug(); 852 + struct eeepc_laptop *eeepc = dev_get_drvdata(device); 849 853 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); 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); 859 867 860 868 return 0; 861 869 } 862 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 + 863 884 /* 864 - * Hwmon 885 + * Hwmon device 865 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 + 866 896 static int eeepc_get_fan_pwm(void) 867 897 { 868 - int value = 0; 898 + u8 value = 0; 869 899 870 - read_acpi_int(NULL, EEEPC_EC_FAN_PWM, &value); 871 - value = value * 255 / 100; 872 - return (value); 900 + ec_read(EEEPC_EC_FAN_PWM, &value); 901 + return value * 255 / 100; 873 902 } 874 903 875 904 static void eeepc_set_fan_pwm(int value) 876 905 { 877 906 value = SENSORS_LIMIT(value, 0, 255); 878 907 value = value * 100 / 255; 879 - ec_write(EEEPC_EC_SC02, value); 908 + ec_write(EEEPC_EC_FAN_PWM, value); 880 909 } 881 910 882 911 static int eeepc_get_fan_rpm(void) 883 912 { 884 - int high = 0; 885 - int low = 0; 913 + u8 high = 0; 914 + u8 low = 0; 886 915 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); 916 + ec_read(EEEPC_EC_FAN_HRPM, &high); 917 + ec_read(EEEPC_EC_FAN_LRPM, &low); 918 + return high << 8 | low; 890 919 } 891 920 892 921 static int eeepc_get_fan_ctrl(void) 893 922 { 894 - int value = 0; 923 + u8 value = 0; 895 924 896 - read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value); 897 - return ((value & 0x02 ? 1 : 0)); 925 + ec_read(EEEPC_EC_FAN_CTRL, &value); 926 + if (value & 0x02) 927 + return 1; /* manual */ 928 + else 929 + return 2; /* automatic */ 898 930 } 899 931 900 932 static void eeepc_set_fan_ctrl(int manual) 901 933 { 902 - int value = 0; 934 + u8 value = 0; 903 935 904 - read_acpi_int(NULL, EEEPC_EC_FAN_CTRL, &value); 905 - if (manual) 936 + ec_read(EEEPC_EC_FAN_CTRL, &value); 937 + if (manual == 1) 906 938 value |= 0x02; 907 939 else 908 940 value &= ~0x02; 909 - ec_write(EEEPC_EC_SFB3, value); 941 + ec_write(EEEPC_EC_FAN_CTRL, value); 910 942 } 911 943 912 944 static ssize_t store_sys_hwmon(void (*set)(int), const char *buf, size_t count) ··· 990 970 .attrs = hwmon_attributes 991 971 }; 992 972 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) 973 + static void eeepc_hwmon_exit(struct eeepc_laptop *eeepc) 1045 974 { 1046 975 struct device *hwmon; 1047 976 1048 - hwmon = eeepc_hwmon_device; 977 + hwmon = eeepc->hwmon_device; 1049 978 if (!hwmon) 1050 - return ; 979 + return; 1051 980 sysfs_remove_group(&hwmon->kobj, 1052 981 &hwmon_attribute_group); 1053 982 hwmon_device_unregister(hwmon); 1054 - eeepc_hwmon_device = NULL; 983 + eeepc->hwmon_device = NULL; 1055 984 } 1056 985 1057 - static int eeepc_new_rfkill(struct rfkill **rfkill, 1058 - const char *name, struct device *dev, 1059 - enum rfkill_type type, int cm) 986 + static int eeepc_hwmon_init(struct eeepc_laptop *eeepc) 1060 987 { 988 + struct device *hwmon; 1061 989 int result; 1062 990 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; 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); 1079 996 } 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(); 997 + eeepc->hwmon_device = hwmon; 998 + result = sysfs_create_group(&hwmon->kobj, 999 + &hwmon_attribute_group); 1000 + if (result) 1001 + eeepc_hwmon_exit(eeepc); 1138 1002 return result; 1139 1003 } 1140 1004 1141 - static int eeepc_backlight_init(struct device *dev) 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) 1142 1043 { 1143 1044 struct backlight_device *bd; 1144 1045 1145 - bd = backlight_device_register(EEEPC_HOTK_FILE, dev, 1146 - NULL, &eeepcbl_ops); 1046 + bd = backlight_device_register(EEEPC_LAPTOP_FILE, 1047 + &eeepc->platform_device->dev, 1048 + eeepc, &eeepcbl_ops); 1147 1049 if (IS_ERR(bd)) { 1148 1050 pr_err("Could not register eeepc backlight device\n"); 1149 - eeepc_backlight_device = NULL; 1051 + eeepc->backlight_device = NULL; 1150 1052 return PTR_ERR(bd); 1151 1053 } 1152 - eeepc_backlight_device = bd; 1054 + eeepc->backlight_device = bd; 1153 1055 bd->props.max_brightness = 15; 1154 - bd->props.brightness = read_brightness(NULL); 1056 + bd->props.brightness = read_brightness(bd); 1155 1057 bd->props.power = FB_BLANK_UNBLANK; 1156 1058 backlight_update_status(bd); 1157 1059 return 0; 1158 1060 } 1159 1061 1160 - static int eeepc_hwmon_init(struct device *dev) 1062 + static void eeepc_backlight_exit(struct eeepc_laptop *eeepc) 1161 1063 { 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; 1064 + if (eeepc->backlight_device) 1065 + backlight_device_unregister(eeepc->backlight_device); 1066 + eeepc->backlight_device = NULL; 1177 1067 } 1178 1068 1179 - static int eeepc_input_init(struct device *dev) 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) 1180 1153 { 1181 1154 const struct key_entry *key; 1182 1155 int result; 1183 1156 1184 - ehotk->inputdev = input_allocate_device(); 1185 - if (!ehotk->inputdev) { 1157 + eeepc->inputdev = input_allocate_device(); 1158 + if (!eeepc->inputdev) { 1186 1159 pr_info("Unable to allocate input device\n"); 1187 1160 return -ENOMEM; 1188 1161 } 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; 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); 1195 1169 1170 + eeepc->keymap = kmemdup(eeepc_keymap, sizeof(eeepc_keymap), 1171 + GFP_KERNEL); 1196 1172 for (key = eeepc_keymap; key->type != KE_END; key++) { 1197 1173 switch (key->type) { 1198 1174 case KE_KEY: 1199 - set_bit(EV_KEY, ehotk->inputdev->evbit); 1200 - set_bit(key->keycode, ehotk->inputdev->keybit); 1175 + set_bit(EV_KEY, eeepc->inputdev->evbit); 1176 + set_bit(key->keycode, eeepc->inputdev->keybit); 1201 1177 break; 1202 1178 } 1203 1179 } 1204 - result = input_register_device(ehotk->inputdev); 1180 + result = input_register_device(eeepc->inputdev); 1205 1181 if (result) { 1206 1182 pr_info("Unable to register input device\n"); 1207 - input_free_device(ehotk->inputdev); 1183 + input_free_device(eeepc->inputdev); 1208 1184 return result; 1209 1185 } 1210 1186 return 0; 1211 1187 } 1212 1188 1213 - static int __devinit eeepc_hotk_add(struct acpi_device *device) 1189 + static void eeepc_input_exit(struct eeepc_laptop *eeepc) 1214 1190 { 1215 - struct device *dev; 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; 1216 1270 int result; 1217 1271 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(); 1272 + result = acpi_bus_get_status(device); 1232 1273 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; 1274 + return result; 1275 + if (!device->status.present) { 1276 + pr_err("Hotkey device not present, aborting\n"); 1277 + return -ENODEV; 1244 1278 } 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 1279 1253 - dev = &platform_device->dev; 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; 1254 1345 1255 1346 if (!acpi_video_backlight_support()) { 1256 - result = eeepc_backlight_init(dev); 1347 + result = eeepc_backlight_init(eeepc); 1257 1348 if (result) 1258 1349 goto fail_backlight; 1259 1350 } else 1260 - pr_info("Backlight controlled by ACPI video " 1261 - "driver\n"); 1351 + pr_info("Backlight controlled by ACPI video driver\n"); 1262 1352 1263 - result = eeepc_input_init(dev); 1353 + result = eeepc_input_init(eeepc); 1264 1354 if (result) 1265 1355 goto fail_input; 1266 1356 1267 - result = eeepc_hwmon_init(dev); 1357 + result = eeepc_hwmon_init(eeepc); 1268 1358 if (result) 1269 1359 goto fail_hwmon; 1270 1360 1271 - result = eeepc_rfkill_init(dev); 1361 + result = eeepc_led_init(eeepc); 1362 + if (result) 1363 + goto fail_led; 1364 + 1365 + result = eeepc_rfkill_init(eeepc); 1272 1366 if (result) 1273 1367 goto fail_rfkill; 1274 1368 1369 + eeepc_device_present = true; 1275 1370 return 0; 1276 1371 1277 1372 fail_rfkill: 1278 - eeepc_hwmon_exit(); 1373 + eeepc_led_exit(eeepc); 1374 + fail_led: 1375 + eeepc_hwmon_exit(eeepc); 1279 1376 fail_hwmon: 1280 - eeepc_input_exit(); 1377 + eeepc_input_exit(eeepc); 1281 1378 fail_input: 1282 - eeepc_backlight_exit(); 1379 + eeepc_backlight_exit(eeepc); 1283 1380 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); 1381 + eeepc_platform_exit(eeepc); 1382 + fail_platform: 1383 + kfree(eeepc); 1294 1384 1295 1385 return result; 1296 1386 } 1297 1387 1298 - static int eeepc_hotk_remove(struct acpi_device *device, int type) 1388 + static int eeepc_acpi_remove(struct acpi_device *device, int type) 1299 1389 { 1300 - if (!device || !acpi_driver_data(device)) 1301 - return -EINVAL; 1390 + struct eeepc_laptop *eeepc = acpi_driver_data(device); 1302 1391 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); 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); 1311 1398 1312 - kfree(ehotk); 1399 + kfree(eeepc); 1313 1400 return 0; 1314 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 + 1315 1423 1316 1424 static int __init eeepc_laptop_init(void) 1317 1425 { 1318 1426 int result; 1319 1427 1320 - if (acpi_disabled) 1321 - return -ENODEV; 1322 - result = acpi_bus_register_driver(&eeepc_hotk_driver); 1428 + result = platform_driver_register(&platform_driver); 1323 1429 if (result < 0) 1324 1430 return result; 1325 - if (!ehotk) { 1326 - acpi_bus_unregister_driver(&eeepc_hotk_driver); 1327 - return -ENODEV; 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; 1328 1438 } 1329 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; 1330 1446 } 1331 1447 1332 1448 static void __exit eeepc_laptop_exit(void) 1333 1449 { 1334 - acpi_bus_unregister_driver(&eeepc_hotk_driver); 1450 + acpi_bus_unregister_driver(&eeepc_acpi_driver); 1451 + platform_driver_unregister(&platform_driver); 1335 1452 } 1336 1453 1337 1454 module_init(eeepc_laptop_init);
+85 -56
drivers/platform/x86/hp-wmi.c
··· 51 51 #define HPWMI_WIRELESS_QUERY 0x5 52 52 #define HPWMI_HOTKEY_QUERY 0xc 53 53 54 + enum hp_wmi_radio { 55 + HPWMI_WIFI = 0, 56 + HPWMI_BLUETOOTH = 1, 57 + HPWMI_WWAN = 2, 58 + }; 59 + 54 60 static int __init hp_wmi_bios_setup(struct platform_device *device); 55 61 static int __exit hp_wmi_bios_remove(struct platform_device *device); 56 62 static int hp_wmi_resume_handler(struct device *device); ··· 181 175 182 176 static int hp_wmi_set_block(void *data, bool blocked) 183 177 { 184 - unsigned long b = (unsigned long) data; 185 - int query = BIT(b + 8) | ((!blocked) << b); 178 + enum hp_wmi_radio r = (enum hp_wmi_radio) data; 179 + int query = BIT(r + 8) | ((!blocked) << r); 186 180 187 181 return hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, query); 188 182 } ··· 191 185 .set_block = hp_wmi_set_block, 192 186 }; 193 187 194 - static bool hp_wmi_wifi_state(void) 188 + static bool hp_wmi_get_sw_state(enum hp_wmi_radio r) 195 189 { 196 190 int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); 191 + int mask = 0x200 << (r * 8); 197 192 198 - if (wireless & 0x100) 193 + if (wireless & mask) 199 194 return false; 200 195 else 201 196 return true; 202 197 } 203 198 204 - static bool hp_wmi_bluetooth_state(void) 199 + static bool hp_wmi_get_hw_state(enum hp_wmi_radio r) 205 200 { 206 201 int wireless = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, 0); 202 + int mask = 0x800 << (r * 8); 207 203 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) 204 + if (wireless & mask) 219 205 return false; 220 206 else 221 207 return true; ··· 332 334 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 333 335 static struct key_entry *key; 334 336 union acpi_object *obj; 337 + int eventcode; 335 338 336 339 wmi_get_event_data(value, &response); 337 340 338 341 obj = (union acpi_object *)response.pointer; 339 342 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 343 + if (!obj || obj->type != ACPI_TYPE_BUFFER || obj->buffer.length != 8) { 377 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); 378 386 } 379 387 380 388 static int __init hp_wmi_input_setup(void) ··· 459 455 wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev, 460 456 RFKILL_TYPE_WLAN, 461 457 &hp_wmi_rfkill_ops, 462 - (void *) 0); 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 463 err = rfkill_register(wifi_rfkill); 464 464 if (err) 465 465 goto register_wifi_error; ··· 473 465 bluetooth_rfkill = rfkill_alloc("hp-bluetooth", &device->dev, 474 466 RFKILL_TYPE_BLUETOOTH, 475 467 &hp_wmi_rfkill_ops, 476 - (void *) 1); 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)); 477 473 err = rfkill_register(bluetooth_rfkill); 478 474 if (err) 479 475 goto register_bluetooth_error; ··· 487 475 wwan_rfkill = rfkill_alloc("hp-wwan", &device->dev, 488 476 RFKILL_TYPE_WWAN, 489 477 &hp_wmi_rfkill_ops, 490 - (void *) 2); 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)); 491 483 err = rfkill_register(wwan_rfkill); 492 484 if (err) 493 485 goto register_wwan_err; ··· 548 532 hp_wmi_tablet_state()); 549 533 input_sync(hp_wmi_input_dev); 550 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)); 551 548 552 549 return 0; 553 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 21 * 02110-1301, USA. 22 22 */ 23 23 24 - #define TPACPI_VERSION "0.23" 25 - #define TPACPI_SYSFS_VERSION 0x020500 24 + #define TPACPI_VERSION "0.24" 25 + #define TPACPI_SYSFS_VERSION 0x020700 26 26 27 27 /* 28 28 * Changelog: ··· 61 61 62 62 #include <linux/nvram.h> 63 63 #include <linux/proc_fs.h> 64 + #include <linux/seq_file.h> 64 65 #include <linux/sysfs.h> 65 66 #include <linux/backlight.h> 66 67 #include <linux/fb.h> ··· 76 75 #include <linux/dmi.h> 77 76 #include <linux/jiffies.h> 78 77 #include <linux/workqueue.h> 78 + 79 + #include <sound/core.h> 80 + #include <sound/control.h> 81 + #include <sound/initval.h> 79 82 80 83 #include <acpi/acpi_drivers.h> 81 84 ··· 236 231 #define TPACPI_DBG_HKEY 0x0008 237 232 #define TPACPI_DBG_FAN 0x0010 238 233 #define TPACPI_DBG_BRGHT 0x0020 234 + #define TPACPI_DBG_MIXER 0x0040 239 235 240 236 #define onoff(status, bit) ((status) & (1 << (bit)) ? "on" : "off") 241 237 #define enabled(status, bit) ((status) & (1 << (bit)) ? "enabled" : "disabled") ··· 262 256 struct ibm_struct { 263 257 char *name; 264 258 265 - int (*read) (char *); 259 + int (*read) (struct seq_file *); 266 260 int (*write) (char *); 267 261 void (*exit) (void); 268 262 void (*resume) (void); ··· 304 298 u32 fan_ctrl_status_undef:1; 305 299 u32 second_fan:1; 306 300 u32 beep_needs_two_args:1; 301 + u32 mixer_no_level_control:1; 307 302 u32 input_device_registered:1; 308 303 u32 platform_drv_registered:1; 309 304 u32 platform_drv_attrs_registered:1; ··· 316 309 317 310 static struct { 318 311 u16 hotkey_mask_ff:1; 312 + u16 volume_ctrl_forbidden:1; 319 313 } tp_warned; 320 314 321 315 struct thinkpad_id_data { ··· 431 423 { .vendor = PCI_VENDOR_ID_LENOVO, \ 432 424 .bios = TPID(__id1, __id2), \ 433 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), \ 434 432 .quirks = (__quirk) } 435 433 436 434 struct tpacpi_quirk { ··· 790 776 **************************************************************************** 791 777 ****************************************************************************/ 792 778 793 - static int dispatch_procfs_read(char *page, char **start, off_t off, 794 - int count, int *eof, void *data) 779 + static int dispatch_proc_show(struct seq_file *m, void *v) 795 780 { 796 - struct ibm_struct *ibm = data; 797 - int len; 781 + struct ibm_struct *ibm = m->private; 798 782 799 783 if (!ibm || !ibm->read) 800 784 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; 785 + return ibm->read(m); 816 786 } 817 787 818 - static int dispatch_procfs_write(struct file *file, 819 - const char __user *userbuf, 820 - unsigned long count, void *data) 788 + static int dispatch_proc_open(struct inode *inode, struct file *file) 821 789 { 822 - struct ibm_struct *ibm = data; 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; 823 798 char *kernbuf; 824 799 int ret; 825 800 ··· 836 833 837 834 return ret; 838 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 + }; 839 845 840 846 static char *next_cmd(char **cmds) 841 847 { ··· 1273 1261 struct tpacpi_rfk *atp_rfk; 1274 1262 int res; 1275 1263 bool sw_state = false; 1264 + bool hw_state; 1276 1265 int sw_status; 1277 1266 1278 1267 BUG_ON(id >= TPACPI_RFK_SW_MAX || tpacpi_rfkill_switches[id]); ··· 1308 1295 rfkill_init_sw_state(atp_rfk->rfkill, sw_state); 1309 1296 } 1310 1297 } 1311 - rfkill_set_hw_state(atp_rfk->rfkill, tpacpi_rfk_check_hwblock_state()); 1298 + hw_state = tpacpi_rfk_check_hwblock_state(); 1299 + rfkill_set_hw_state(atp_rfk->rfkill, hw_state); 1312 1300 1313 1301 res = rfkill_register(atp_rfk->rfkill); 1314 1302 if (res < 0) { ··· 1322 1308 } 1323 1309 1324 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"); 1325 1314 return 0; 1326 1315 } 1327 1316 ··· 1397 1380 } 1398 1381 1399 1382 /* procfs -------------------------------------------------------------- */ 1400 - static int tpacpi_rfk_procfs_read(const enum tpacpi_rfk_id id, char *p) 1383 + static int tpacpi_rfk_procfs_read(const enum tpacpi_rfk_id id, struct seq_file *m) 1401 1384 { 1402 - int len = 0; 1403 - 1404 1385 if (id >= TPACPI_RFK_SW_MAX) 1405 - len += sprintf(p + len, "status:\t\tnot supported\n"); 1386 + seq_printf(m, "status:\t\tnot supported\n"); 1406 1387 else { 1407 1388 int status; 1408 1389 ··· 1414 1399 return status; 1415 1400 } 1416 1401 1417 - len += sprintf(p + len, "status:\t\t%s\n", 1402 + seq_printf(m, "status:\t\t%s\n", 1418 1403 (status == TPACPI_RFK_RADIO_ON) ? 1419 1404 "enabled" : "disabled"); 1420 - len += sprintf(p + len, "commands:\tenable, disable\n"); 1405 + seq_printf(m, "commands:\tenable, disable\n"); 1421 1406 } 1422 1407 1423 - return len; 1408 + return 0; 1424 1409 } 1425 1410 1426 1411 static int tpacpi_rfk_procfs_write(const enum tpacpi_rfk_id id, char *buf) ··· 1791 1776 1792 1777 TPV_QL1('7', '9', 'E', '3', '5', '0'), /* T60/p */ 1793 1778 TPV_QL1('7', 'C', 'D', '2', '2', '2'), /* R60, R60i */ 1794 - TPV_QL0('7', 'E', 'D', '0'), /* R60e, R60i */ 1779 + TPV_QL1('7', 'E', 'D', '0', '1', '5'), /* R60e, R60i */ 1795 1780 1796 1781 /* BIOS FW BIOS VERS EC FW EC VERS */ 1797 1782 TPV_QI2('1', 'W', '9', '0', '1', 'V', '2', '8'), /* R50e (1) */ ··· 1807 1792 TPV_QI1('7', '4', '6', '4', '2', '7'), /* X41 (0) */ 1808 1793 TPV_QI1('7', '5', '6', '0', '2', '0'), /* X41t (0) */ 1809 1794 1810 - TPV_QL0('7', 'B', 'D', '7'), /* X60/s */ 1811 - TPV_QL0('7', 'J', '3', '0'), /* X60t */ 1795 + TPV_QL1('7', 'B', 'D', '7', '4', '0'), /* X60/s */ 1796 + TPV_QL1('7', 'J', '3', '0', '1', '3'), /* X60t */ 1812 1797 1813 1798 /* (0) - older versions lack DMI EC fw string and functionality */ 1814 1799 /* (1) - older versions known to lack functionality */ ··· 1898 1883 return 0; 1899 1884 } 1900 1885 1901 - static int thinkpad_acpi_driver_read(char *p) 1886 + static int thinkpad_acpi_driver_read(struct seq_file *m) 1902 1887 { 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; 1888 + seq_printf(m, "driver:\t\t%s\n", TPACPI_DESC); 1889 + seq_printf(m, "version:\t%s\n", TPACPI_VERSION); 1890 + return 0; 1909 1891 } 1910 1892 1911 1893 static struct ibm_struct thinkpad_acpi_driver_data = { ··· 2198 2186 fwmask, hotkey_acpi_mask); 2199 2187 } 2200 2188 2201 - hotkey_mask_warn_incomplete_mask(); 2189 + if (tpacpi_lifecycle != TPACPI_LIFE_EXITING) 2190 + hotkey_mask_warn_incomplete_mask(); 2202 2191 2203 2192 return rc; 2204 2193 } ··· 3195 3182 int res, i; 3196 3183 int status; 3197 3184 int hkeyv; 3185 + bool radiosw_state = false; 3186 + bool tabletsw_state = false; 3198 3187 3199 3188 unsigned long quirks; 3200 3189 ··· 3302 3287 #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES 3303 3288 if (dbg_wlswemul) { 3304 3289 tp_features.hotkey_wlsw = 1; 3290 + radiosw_state = !!tpacpi_wlsw_emulstate; 3305 3291 printk(TPACPI_INFO 3306 3292 "radio switch emulation enabled\n"); 3307 3293 } else ··· 3310 3294 /* Not all thinkpads have a hardware radio switch */ 3311 3295 if (acpi_evalf(hkey_handle, &status, "WLSW", "qd")) { 3312 3296 tp_features.hotkey_wlsw = 1; 3297 + radiosw_state = !!status; 3313 3298 printk(TPACPI_INFO 3314 3299 "radio switch found; radios are %s\n", 3315 3300 enabled(status, 0)); ··· 3322 3305 /* For X41t, X60t, X61t Tablets... */ 3323 3306 if (!res && acpi_evalf(hkey_handle, &status, "MHKG", "qd")) { 3324 3307 tp_features.hotkey_tablet = 1; 3308 + tabletsw_state = !!(status & TP_HOTKEY_TABLET_MASK); 3325 3309 printk(TPACPI_INFO 3326 3310 "possible tablet mode switch found; " 3327 3311 "ThinkPad in %s mode\n", 3328 - (status & TP_HOTKEY_TABLET_MASK)? 3329 - "tablet" : "laptop"); 3312 + (tabletsw_state) ? "tablet" : "laptop"); 3330 3313 res = add_to_attr_set(hotkey_dev_attributes, 3331 3314 &dev_attr_hotkey_tablet_mode.attr); 3332 3315 } ··· 3361 3344 TPACPI_HOTKEY_MAP_SIZE); 3362 3345 } 3363 3346 3364 - set_bit(EV_KEY, tpacpi_inputdev->evbit); 3365 - set_bit(EV_MSC, tpacpi_inputdev->evbit); 3366 - set_bit(MSC_SCAN, tpacpi_inputdev->mscbit); 3347 + input_set_capability(tpacpi_inputdev, EV_MSC, MSC_SCAN); 3367 3348 tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE; 3368 3349 tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN; 3369 3350 tpacpi_inputdev->keycode = hotkey_keycode_map; 3370 3351 for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) { 3371 3352 if (hotkey_keycode_map[i] != KEY_RESERVED) { 3372 - set_bit(hotkey_keycode_map[i], 3373 - tpacpi_inputdev->keybit); 3353 + input_set_capability(tpacpi_inputdev, EV_KEY, 3354 + hotkey_keycode_map[i]); 3374 3355 } else { 3375 3356 if (i < sizeof(hotkey_reserved_mask)*8) 3376 3357 hotkey_reserved_mask |= 1 << i; ··· 3376 3361 } 3377 3362 3378 3363 if (tp_features.hotkey_wlsw) { 3379 - set_bit(EV_SW, tpacpi_inputdev->evbit); 3380 - set_bit(SW_RFKILL_ALL, tpacpi_inputdev->swbit); 3364 + input_set_capability(tpacpi_inputdev, EV_SW, SW_RFKILL_ALL); 3365 + input_report_switch(tpacpi_inputdev, 3366 + SW_RFKILL_ALL, radiosw_state); 3381 3367 } 3382 3368 if (tp_features.hotkey_tablet) { 3383 - set_bit(EV_SW, tpacpi_inputdev->evbit); 3384 - set_bit(SW_TABLET_MODE, tpacpi_inputdev->swbit); 3369 + input_set_capability(tpacpi_inputdev, EV_SW, SW_TABLET_MODE); 3370 + input_report_switch(tpacpi_inputdev, 3371 + SW_TABLET_MODE, tabletsw_state); 3385 3372 } 3386 3373 3387 3374 /* Do not issue duplicate brightness change events to ··· 3450 3433 tpacpi_inputdev->close = &hotkey_inputdev_close; 3451 3434 3452 3435 hotkey_poll_setup_safe(true); 3453 - tpacpi_send_radiosw_update(); 3454 - tpacpi_input_send_tabletsw(); 3455 3436 3456 3437 return 0; 3457 3438 ··· 3557 3542 } 3558 3543 } 3559 3544 3545 + static void thermal_dump_all_sensors(void); 3546 + 3560 3547 static bool hotkey_notify_thermal(const u32 hkey, 3561 3548 bool *send_acpi_ev, 3562 3549 bool *ignore_acpi_ev) 3563 3550 { 3551 + bool known = true; 3552 + 3564 3553 /* 0x6000-0x6FFF: thermal alarms */ 3565 3554 *send_acpi_ev = true; 3566 3555 *ignore_acpi_ev = false; 3567 3556 3568 3557 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 3558 case TP_HKEY_EV_THM_TABLE_CHANGED: 3593 3559 printk(TPACPI_INFO 3594 3560 "EC reports that Thermal Table has changed\n"); 3595 3561 /* recommended action: do nothing, we don't have 3596 3562 * Lenovo ATM information */ 3597 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; 3598 3587 default: 3599 3588 printk(TPACPI_ALERT 3600 3589 "THERMAL ALERT: unknown thermal alarm received\n"); 3601 - return false; 3590 + known = false; 3602 3591 } 3592 + 3593 + thermal_dump_all_sensors(); 3594 + 3595 + return known; 3603 3596 } 3604 3597 3605 3598 static void hotkey_notify(struct ibm_struct *ibm, u32 event) ··· 3750 3727 } 3751 3728 3752 3729 /* procfs -------------------------------------------------------------- */ 3753 - static int hotkey_read(char *p) 3730 + static int hotkey_read(struct seq_file *m) 3754 3731 { 3755 3732 int res, status; 3756 - int len = 0; 3757 3733 3758 3734 if (!tp_features.hotkey) { 3759 - len += sprintf(p + len, "status:\t\tnot supported\n"); 3760 - return len; 3735 + seq_printf(m, "status:\t\tnot supported\n"); 3736 + return 0; 3761 3737 } 3762 3738 3763 3739 if (mutex_lock_killable(&hotkey_mutex)) ··· 3768 3746 if (res) 3769 3747 return res; 3770 3748 3771 - len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0)); 3749 + seq_printf(m, "status:\t\t%s\n", enabled(status, 0)); 3772 3750 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"); 3751 + seq_printf(m, "mask:\t\t0x%08x\n", hotkey_user_mask); 3752 + seq_printf(m, "commands:\tenable, disable, reset, <mask>\n"); 3776 3753 } else { 3777 - len += sprintf(p + len, "mask:\t\tnot supported\n"); 3778 - len += sprintf(p + len, "commands:\tenable, disable, reset\n"); 3754 + seq_printf(m, "mask:\t\tnot supported\n"); 3755 + seq_printf(m, "commands:\tenable, disable, reset\n"); 3779 3756 } 3780 3757 3781 - return len; 3758 + return 0; 3782 3759 } 3783 3760 3784 3761 static void hotkey_enabledisable_warn(bool enable) ··· 3884 3863 3885 3864 #define TPACPI_RFK_BLUETOOTH_SW_NAME "tpacpi_bluetooth_sw" 3886 3865 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 3866 static int bluetooth_get_status(void) 3897 3867 { 3898 3868 int status; ··· 3917 3905 #endif 3918 3906 3919 3907 /* We make sure to keep TP_ACPI_BLUETOOTH_RESUMECTRL off */ 3908 + status = TP_ACPI_BLUETOOTH_RESUMECTRL; 3920 3909 if (state == TPACPI_RFK_RADIO_ON) 3921 - status = TP_ACPI_BLUETOOTH_RADIOSSW; 3922 - else 3923 - status = 0; 3910 + status |= TP_ACPI_BLUETOOTH_RADIOSSW; 3924 3911 3925 3912 if (!acpi_evalf(hkey_handle, NULL, "SBDC", "vd", status)) 3926 3913 return -EIO; ··· 4043 4032 } 4044 4033 4045 4034 /* procfs -------------------------------------------------------------- */ 4046 - static int bluetooth_read(char *p) 4035 + static int bluetooth_read(struct seq_file *m) 4047 4036 { 4048 - return tpacpi_rfk_procfs_read(TPACPI_RFK_BLUETOOTH_SW_ID, p); 4037 + return tpacpi_rfk_procfs_read(TPACPI_RFK_BLUETOOTH_SW_ID, m); 4049 4038 } 4050 4039 4051 4040 static int bluetooth_write(char *buf) ··· 4058 4047 .read = bluetooth_read, 4059 4048 .write = bluetooth_write, 4060 4049 .exit = bluetooth_exit, 4061 - .suspend = bluetooth_suspend, 4062 4050 .shutdown = bluetooth_shutdown, 4063 4051 }; 4064 4052 ··· 4074 4064 }; 4075 4065 4076 4066 #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 4067 4087 4068 static int wan_get_status(void) 4088 4069 { ··· 4107 4106 } 4108 4107 #endif 4109 4108 4110 - /* We make sure to keep TP_ACPI_WANCARD_RESUMECTRL off */ 4109 + /* We make sure to set TP_ACPI_WANCARD_RESUMECTRL */ 4110 + status = TP_ACPI_WANCARD_RESUMECTRL; 4111 4111 if (state == TPACPI_RFK_RADIO_ON) 4112 - status = TP_ACPI_WANCARD_RADIOSSW; 4113 - else 4114 - status = 0; 4112 + status |= TP_ACPI_WANCARD_RADIOSSW; 4115 4113 4116 4114 if (!acpi_evalf(hkey_handle, NULL, "SWAN", "vd", status)) 4117 4115 return -EIO; ··· 4233 4233 } 4234 4234 4235 4235 /* procfs -------------------------------------------------------------- */ 4236 - static int wan_read(char *p) 4236 + static int wan_read(struct seq_file *m) 4237 4237 { 4238 - return tpacpi_rfk_procfs_read(TPACPI_RFK_WWAN_SW_ID, p); 4238 + return tpacpi_rfk_procfs_read(TPACPI_RFK_WWAN_SW_ID, m); 4239 4239 } 4240 4240 4241 4241 static int wan_write(char *buf) ··· 4248 4248 .read = wan_read, 4249 4249 .write = wan_write, 4250 4250 .exit = wan_exit, 4251 - .suspend = wan_suspend, 4252 4251 .shutdown = wan_shutdown, 4253 4252 }; 4254 4253 ··· 4610 4611 /* not reached */ 4611 4612 } 4612 4613 4613 - static int video_read(char *p) 4614 + static int video_read(struct seq_file *m) 4614 4615 { 4615 4616 int status, autosw; 4616 - int len = 0; 4617 4617 4618 4618 if (video_supported == TPACPI_VIDEO_NONE) { 4619 - len += sprintf(p + len, "status:\t\tnot supported\n"); 4620 - return len; 4619 + seq_printf(m, "status:\t\tnot supported\n"); 4620 + return 0; 4621 4621 } 4622 4622 4623 4623 status = video_outputsw_get(); ··· 4627 4629 if (autosw < 0) 4628 4630 return autosw; 4629 4631 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)); 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)); 4633 4635 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"); 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"); 4638 4640 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"); 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"); 4642 4644 4643 - return len; 4645 + return 0; 4644 4646 } 4645 4647 4646 4648 static int video_write(char *buf) ··· 4832 4834 flush_workqueue(tpacpi_wq); 4833 4835 } 4834 4836 4835 - static int light_read(char *p) 4837 + static int light_read(struct seq_file *m) 4836 4838 { 4837 - int len = 0; 4838 4839 int status; 4839 4840 4840 4841 if (!tp_features.light) { 4841 - len += sprintf(p + len, "status:\t\tnot supported\n"); 4842 + seq_printf(m, "status:\t\tnot supported\n"); 4842 4843 } else if (!tp_features.light_status) { 4843 - len += sprintf(p + len, "status:\t\tunknown\n"); 4844 - len += sprintf(p + len, "commands:\ton, off\n"); 4844 + seq_printf(m, "status:\t\tunknown\n"); 4845 + seq_printf(m, "commands:\ton, off\n"); 4845 4846 } else { 4846 4847 status = light_get_status(); 4847 4848 if (status < 0) 4848 4849 return status; 4849 - len += sprintf(p + len, "status:\t\t%s\n", onoff(status, 0)); 4850 - len += sprintf(p + len, "commands:\ton, off\n"); 4850 + seq_printf(m, "status:\t\t%s\n", onoff(status, 0)); 4851 + seq_printf(m, "commands:\ton, off\n"); 4851 4852 } 4852 4853 4853 - return len; 4854 + return 0; 4854 4855 } 4855 4856 4856 4857 static int light_write(char *buf) ··· 4927 4930 device_remove_file(&tpacpi_pdev->dev, &dev_attr_cmos_command); 4928 4931 } 4929 4932 4930 - static int cmos_read(char *p) 4933 + static int cmos_read(struct seq_file *m) 4931 4934 { 4932 - int len = 0; 4933 - 4934 4935 /* cmos not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p, 4935 4936 R30, R31, T20-22, X20-21 */ 4936 4937 if (!cmos_handle) 4937 - len += sprintf(p + len, "status:\t\tnot supported\n"); 4938 + seq_printf(m, "status:\t\tnot supported\n"); 4938 4939 else { 4939 - len += sprintf(p + len, "status:\t\tsupported\n"); 4940 - len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-21)\n"); 4940 + seq_printf(m, "status:\t\tsupported\n"); 4941 + seq_printf(m, "commands:\t<cmd> (<cmd> is 0-21)\n"); 4941 4942 } 4942 4943 4943 - return len; 4944 + return 0; 4944 4945 } 4945 4946 4946 4947 static int cmos_write(char *buf) ··· 5313 5318 ((s) == TPACPI_LED_OFF ? "off" : \ 5314 5319 ((s) == TPACPI_LED_ON ? "on" : "blinking")) 5315 5320 5316 - static int led_read(char *p) 5321 + static int led_read(struct seq_file *m) 5317 5322 { 5318 - int len = 0; 5319 - 5320 5323 if (!led_supported) { 5321 - len += sprintf(p + len, "status:\t\tnot supported\n"); 5322 - return len; 5324 + seq_printf(m, "status:\t\tnot supported\n"); 5325 + return 0; 5323 5326 } 5324 - len += sprintf(p + len, "status:\t\tsupported\n"); 5327 + seq_printf(m, "status:\t\tsupported\n"); 5325 5328 5326 5329 if (led_supported == TPACPI_LED_570) { 5327 5330 /* 570 */ ··· 5328 5335 status = led_get_status(i); 5329 5336 if (status < 0) 5330 5337 return -EIO; 5331 - len += sprintf(p + len, "%d:\t\t%s\n", 5338 + seq_printf(m, "%d:\t\t%s\n", 5332 5339 i, str_led_status(status)); 5333 5340 } 5334 5341 } 5335 5342 5336 - len += sprintf(p + len, "commands:\t" 5343 + seq_printf(m, "commands:\t" 5337 5344 "<led> on, <led> off, <led> blink (<led> is 0-15)\n"); 5338 5345 5339 - return len; 5346 + return 0; 5340 5347 } 5341 5348 5342 5349 static int led_write(char *buf) ··· 5409 5416 return (beep_handle)? 0 : 1; 5410 5417 } 5411 5418 5412 - static int beep_read(char *p) 5419 + static int beep_read(struct seq_file *m) 5413 5420 { 5414 - int len = 0; 5415 - 5416 5421 if (!beep_handle) 5417 - len += sprintf(p + len, "status:\t\tnot supported\n"); 5422 + seq_printf(m, "status:\t\tnot supported\n"); 5418 5423 else { 5419 - len += sprintf(p + len, "status:\t\tsupported\n"); 5420 - len += sprintf(p + len, "commands:\t<cmd> (<cmd> is 0-17)\n"); 5424 + seq_printf(m, "status:\t\tsupported\n"); 5425 + seq_printf(m, "commands:\t<cmd> (<cmd> is 0-17)\n"); 5421 5426 } 5422 5427 5423 - return len; 5428 + return 0; 5424 5429 } 5425 5430 5426 5431 static int beep_write(char *buf) ··· 5471 5480 TP_EC_THERMAL_TMP0 = 0x78, /* ACPI EC regs TMP 0..7 */ 5472 5481 TP_EC_THERMAL_TMP8 = 0xC0, /* ACPI EC regs TMP 8..15 */ 5473 5482 TP_EC_THERMAL_TMP_NA = -128, /* ACPI EC sensor not available */ 5483 + 5484 + TPACPI_THERMAL_SENSOR_NA = -128000, /* Sensor not available */ 5474 5485 }; 5486 + 5475 5487 5476 5488 #define TPACPI_MAX_THERMAL_SENSORS 16 /* Max thermal sensors supported */ 5477 5489 struct ibm_thermal_sensors_struct { ··· 5565 5571 return n; 5566 5572 } 5567 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 + 5568 5596 /* sysfs temp##_input -------------------------------------------------- */ 5569 5597 5570 5598 static ssize_t thermal_temp_input_show(struct device *dev, ··· 5602 5586 res = thermal_get_sensor(idx, &value); 5603 5587 if (res) 5604 5588 return res; 5605 - if (value == TP_EC_THERMAL_TMP_NA * 1000) 5589 + if (value == TPACPI_THERMAL_SENSOR_NA) 5606 5590 return -ENXIO; 5607 5591 5608 5592 return snprintf(buf, PAGE_SIZE, "%d\n", value); ··· 5779 5763 } 5780 5764 } 5781 5765 5782 - static int thermal_read(char *p) 5766 + static int thermal_read(struct seq_file *m) 5783 5767 { 5784 - int len = 0; 5785 5768 int n, i; 5786 5769 struct ibm_thermal_sensors_struct t; 5787 5770 ··· 5788 5773 if (unlikely(n < 0)) 5789 5774 return n; 5790 5775 5791 - len += sprintf(p + len, "temperatures:\t"); 5776 + seq_printf(m, "temperatures:\t"); 5792 5777 5793 5778 if (n > 0) { 5794 5779 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); 5780 + seq_printf(m, "%d ", t.temp[i] / 1000); 5781 + seq_printf(m, "%d\n", t.temp[i] / 1000); 5797 5782 } else 5798 - len += sprintf(p + len, "not supported\n"); 5783 + seq_printf(m, "not supported\n"); 5799 5784 5800 - return len; 5785 + return 0; 5801 5786 } 5802 5787 5803 5788 static struct ibm_struct thermal_driver_data = { ··· 5812 5797 5813 5798 static u8 ecdump_regs[256]; 5814 5799 5815 - static int ecdump_read(char *p) 5800 + static int ecdump_read(struct seq_file *m) 5816 5801 { 5817 - int len = 0; 5818 5802 int i, j; 5819 5803 u8 v; 5820 5804 5821 - len += sprintf(p + len, "EC " 5805 + seq_printf(m, "EC " 5822 5806 " +00 +01 +02 +03 +04 +05 +06 +07" 5823 5807 " +08 +09 +0a +0b +0c +0d +0e +0f\n"); 5824 5808 for (i = 0; i < 256; i += 16) { 5825 - len += sprintf(p + len, "EC 0x%02x:", i); 5809 + seq_printf(m, "EC 0x%02x:", i); 5826 5810 for (j = 0; j < 16; j++) { 5827 5811 if (!acpi_ec_read(i + j, &v)) 5828 5812 break; 5829 5813 if (v != ecdump_regs[i + j]) 5830 - len += sprintf(p + len, " *%02x", v); 5814 + seq_printf(m, " *%02x", v); 5831 5815 else 5832 - len += sprintf(p + len, " %02x", v); 5816 + seq_printf(m, " %02x", v); 5833 5817 ecdump_regs[i + j] = v; 5834 5818 } 5835 - len += sprintf(p + len, "\n"); 5819 + seq_putc(m, '\n'); 5836 5820 if (j != 16) 5837 5821 break; 5838 5822 } 5839 5823 5840 5824 /* These are way too dangerous to advertise openly... */ 5841 5825 #if 0 5842 - len += sprintf(p + len, "commands:\t0x<offset> 0x<value>" 5826 + seq_printf(m, "commands:\t0x<offset> 0x<value>" 5843 5827 " (<offset> is 00-ff, <value> is 00-ff)\n"); 5844 - len += sprintf(p + len, "commands:\t0x<offset> <value> " 5828 + seq_printf(m, "commands:\t0x<offset> <value> " 5845 5829 " (<offset> is 00-ff, <value> is 0-255)\n"); 5846 5830 #endif 5847 - return len; 5831 + return 0; 5848 5832 } 5849 5833 5850 5834 static int ecdump_write(char *buf) ··· 6106 6092 return status & TP_EC_BACKLIGHT_LVLMSK; 6107 6093 } 6108 6094 6095 + static void tpacpi_brightness_notify_change(void) 6096 + { 6097 + backlight_force_update(ibm_backlight_device, 6098 + BACKLIGHT_UPDATE_HOTKEY); 6099 + } 6100 + 6109 6101 static struct backlight_ops ibm_backlight_data = { 6110 6102 .get_brightness = brightness_get, 6111 6103 .update_status = brightness_update_status, ··· 6140 6120 6141 6121 /* Models with Intel Extreme Graphics 2 */ 6142 6122 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), 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), 6145 6125 6146 6126 /* Models with Intel GMA900 */ 6147 6127 TPACPI_Q_IBM('7', '0', TPACPI_BRGHT_Q_NOEC), /* T43, R52 */ ··· 6266 6246 ibm_backlight_device->props.brightness = b & TP_EC_BACKLIGHT_LVLMSK; 6267 6247 backlight_update_status(ibm_backlight_device); 6268 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);; 6269 6255 return 0; 6270 6256 } 6271 6257 ··· 6296 6270 tpacpi_brightness_checkpoint_nvram(); 6297 6271 } 6298 6272 6299 - static int brightness_read(char *p) 6273 + static int brightness_read(struct seq_file *m) 6300 6274 { 6301 - int len = 0; 6302 6275 int level; 6303 6276 6304 6277 level = brightness_get(NULL); 6305 6278 if (level < 0) { 6306 - len += sprintf(p + len, "level:\t\tunreadable\n"); 6279 + seq_printf(m, "level:\t\tunreadable\n"); 6307 6280 } 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>" 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>" 6311 6284 " (<level> is 0-%d)\n", 6312 6285 (tp_features.bright_16levels) ? 15 : 7); 6313 6286 } 6314 6287 6315 - return len; 6288 + return 0; 6316 6289 } 6317 6290 6318 6291 static int brightness_write(char *buf) ··· 6347 6322 * Doing it this way makes the syscall restartable in case of EINTR 6348 6323 */ 6349 6324 rc = brightness_set(level); 6325 + if (!rc && ibm_backlight_device) 6326 + backlight_force_update(ibm_backlight_device, 6327 + BACKLIGHT_UPDATE_SYSFS); 6350 6328 return (rc == -EINTR)? -ERESTARTSYS : rc; 6351 6329 } 6352 6330 ··· 6366 6338 * Volume subdriver 6367 6339 */ 6368 6340 6369 - static int volume_offset = 0x30; 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 + */ 6370 6358 6371 - static int volume_read(char *p) 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) 6372 6417 { 6373 - int len = 0; 6374 - u8 level; 6418 + u8 lec = 0; 6419 + u8 b_nvram; 6420 + u8 ec_mask; 6375 6421 6376 - if (!acpi_ec_read(volume_offset, &level)) { 6377 - len += sprintf(p + len, "level:\t\tunreadable\n"); 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); 6378 6451 } 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"); 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); 6384 6455 } 6385 6456 6386 - return len; 6457 + unlock: 6458 + mutex_unlock(&volume_mutex); 6387 6459 } 6388 6460 6389 - static int volume_write(char *buf) 6461 + static int volume_get_status_ec(u8 *status) 6390 6462 { 6391 - int cmos_cmd, inc, i; 6392 - u8 level, mute; 6393 - int new_level, new_mute; 6394 - char *cmd; 6463 + u8 s; 6395 6464 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; 6465 + if (!acpi_ec_read(TP_EC_AUDIO, &s)) 6466 + return -EIO; 6401 6467 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; 6468 + *status = s; 6419 6469 6420 - if (new_level != level) { 6421 - /* mute doesn't change */ 6470 + dbg_printk(TPACPI_DBG_MIXER, "status 0x%02x\n", s); 6422 6471 6423 - cmos_cmd = (new_level > level) ? 6424 - TP_CMOS_VOLUME_UP : TP_CMOS_VOLUME_DOWN; 6425 - inc = new_level > level ? 1 : -1; 6472 + return 0; 6473 + } 6426 6474 6427 - if (mute && (issue_thinkpad_cmos_command(cmos_cmd) || 6428 - !acpi_ec_write(volume_offset, level))) 6429 - return -EIO; 6475 + static int volume_get_status(u8 *status) 6476 + { 6477 + return volume_get_status_ec(status); 6478 + } 6430 6479 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; 6480 + static int volume_set_status_ec(const u8 status) 6481 + { 6482 + if (!acpi_ec_write(TP_EC_AUDIO, status)) 6483 + return -EIO; 6435 6484 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 - } 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; 6441 6718 } 6719 + data->ctl_vol_id = &ctl_vol->id; 6720 + } 6442 6721 6443 - if (new_mute != mute) { 6444 - /* level doesn't change */ 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; 6445 6729 6446 - cmos_cmd = (new_mute) ? 6447 - TP_CMOS_VOLUME_MUTE : TP_CMOS_VOLUME_UP; 6730 + snd_card_set_dev(card, &tpacpi_pdev->dev); 6731 + rc = snd_card_register(card); 6448 6732 6449 - if (issue_thinkpad_cmos_command(cmos_cmd) || 6450 - !acpi_ec_write(volume_offset, level + new_mute)) 6451 - return -EIO; 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 + } 6452 6900 } 6453 6901 } 6454 6902 6455 6903 return 0; 6456 6904 } 6457 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 + 6458 6981 static struct ibm_struct volume_driver_data = { 6459 6982 .name = "volume", 6460 6983 .read = volume_read, 6461 6984 .write = volume_write, 6985 + .exit = volume_exit, 6986 + .suspend = volume_suspend, 6987 + .resume = volume_resume, 6988 + .shutdown = volume_shutdown, 6462 6989 }; 6463 6990 6464 6991 /************************************************************************* ··· 8090 7507 } 8091 7508 } 8092 7509 8093 - static int fan_read(char *p) 7510 + static int fan_read(struct seq_file *m) 8094 7511 { 8095 - int len = 0; 8096 7512 int rc; 8097 7513 u8 status; 8098 7514 unsigned int speed = 0; ··· 8103 7521 if (rc < 0) 8104 7522 return rc; 8105 7523 8106 - len += sprintf(p + len, "status:\t\t%s\n" 7524 + seq_printf(m, "status:\t\t%s\n" 8107 7525 "level:\t\t%d\n", 8108 7526 (status != 0) ? "enabled" : "disabled", status); 8109 7527 break; ··· 8114 7532 if (rc < 0) 8115 7533 return rc; 8116 7534 8117 - len += sprintf(p + len, "status:\t\t%s\n", 7535 + seq_printf(m, "status:\t\t%s\n", 8118 7536 (status != 0) ? "enabled" : "disabled"); 8119 7537 8120 7538 rc = fan_get_speed(&speed); 8121 7539 if (rc < 0) 8122 7540 return rc; 8123 7541 8124 - len += sprintf(p + len, "speed:\t\t%d\n", speed); 7542 + seq_printf(m, "speed:\t\t%d\n", speed); 8125 7543 8126 7544 if (status & TP_EC_FAN_FULLSPEED) 8127 7545 /* Disengaged mode takes precedence */ 8128 - len += sprintf(p + len, "level:\t\tdisengaged\n"); 7546 + seq_printf(m, "level:\t\tdisengaged\n"); 8129 7547 else if (status & TP_EC_FAN_AUTO) 8130 - len += sprintf(p + len, "level:\t\tauto\n"); 7548 + seq_printf(m, "level:\t\tauto\n"); 8131 7549 else 8132 - len += sprintf(p + len, "level:\t\t%d\n", status); 7550 + seq_printf(m, "level:\t\t%d\n", status); 8133 7551 break; 8134 7552 8135 7553 case TPACPI_FAN_NONE: 8136 7554 default: 8137 - len += sprintf(p + len, "status:\t\tnot supported\n"); 7555 + seq_printf(m, "status:\t\tnot supported\n"); 8138 7556 } 8139 7557 8140 7558 if (fan_control_commands & TPACPI_FAN_CMD_LEVEL) { 8141 - len += sprintf(p + len, "commands:\tlevel <level>"); 7559 + seq_printf(m, "commands:\tlevel <level>"); 8142 7560 8143 7561 switch (fan_control_access_mode) { 8144 7562 case TPACPI_FAN_WR_ACPI_SFAN: 8145 - len += sprintf(p + len, " (<level> is 0-7)\n"); 7563 + seq_printf(m, " (<level> is 0-7)\n"); 8146 7564 break; 8147 7565 8148 7566 default: 8149 - len += sprintf(p + len, " (<level> is 0-7, " 7567 + seq_printf(m, " (<level> is 0-7, " 8150 7568 "auto, disengaged, full-speed)\n"); 8151 7569 break; 8152 7570 } 8153 7571 } 8154 7572 8155 7573 if (fan_control_commands & TPACPI_FAN_CMD_ENABLE) 8156 - len += sprintf(p + len, "commands:\tenable, disable\n" 7574 + seq_printf(m, "commands:\tenable, disable\n" 8157 7575 "commands:\twatchdog <timeout> (<timeout> " 8158 7576 "is 0 (off), 1-120 (seconds))\n"); 8159 7577 8160 7578 if (fan_control_commands & TPACPI_FAN_CMD_SPEED) 8161 - len += sprintf(p + len, "commands:\tspeed <speed>" 7579 + seq_printf(m, "commands:\tspeed <speed>" 8162 7580 " (<speed> is 0-65535)\n"); 8163 7581 8164 - return len; 7582 + return 0; 8165 7583 } 8166 7584 8167 7585 static int fan_write_cmd_level(const char *cmd, int *rc) ··· 8303 7721 */ 8304 7722 static void tpacpi_driver_event(const unsigned int hkey_event) 8305 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 + } 8306 7739 } 8307 - 8308 - 8309 7740 8310 7741 static void hotkey_driver_event(const unsigned int scancode) 8311 7742 { ··· 8448 7853 "%s installed\n", ibm->name); 8449 7854 8450 7855 if (ibm->read) { 8451 - entry = create_proc_entry(ibm->name, 8452 - S_IFREG | S_IRUGO | S_IWUSR, 8453 - proc_dir); 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); 8454 7863 if (!entry) { 8455 7864 printk(TPACPI_ERR "unable to create proc entry %s\n", 8456 7865 ibm->name); 8457 7866 ret = -ENODEV; 8458 7867 goto err_out; 8459 7868 } 8460 - entry->data = ibm; 8461 - entry->read_proc = &dispatch_procfs_read; 8462 - if (ibm->write) 8463 - entry->write_proc = &dispatch_procfs_write; 8464 7869 ibm->flags.proc_created = 1; 8465 7870 } 8466 7871 ··· 8672 8077 .data = &brightness_driver_data, 8673 8078 }, 8674 8079 { 8080 + .init = volume_init, 8675 8081 .data = &volume_driver_data, 8676 8082 }, 8677 8083 { ··· 8708 8112 return -EINVAL; 8709 8113 } 8710 8114 8711 - module_param(experimental, int, 0); 8115 + module_param(experimental, int, 0444); 8712 8116 MODULE_PARM_DESC(experimental, 8713 8117 "Enables experimental features when non-zero"); 8714 8118 8715 8119 module_param_named(debug, dbg_level, uint, 0); 8716 8120 MODULE_PARM_DESC(debug, "Sets debug level bit-mask"); 8717 8121 8718 - module_param(force_load, bool, 0); 8122 + module_param(force_load, bool, 0444); 8719 8123 MODULE_PARM_DESC(force_load, 8720 8124 "Attempts to load the driver even on a " 8721 8125 "mis-identified ThinkPad when true"); 8722 8126 8723 - module_param_named(fan_control, fan_control_allowed, bool, 0); 8127 + module_param_named(fan_control, fan_control_allowed, bool, 0444); 8724 8128 MODULE_PARM_DESC(fan_control, 8725 8129 "Enables setting fan parameters features when true"); 8726 8130 8727 - module_param_named(brightness_mode, brightness_mode, uint, 0); 8131 + module_param_named(brightness_mode, brightness_mode, uint, 0444); 8728 8132 MODULE_PARM_DESC(brightness_mode, 8729 8133 "Selects brightness control strategy: " 8730 8134 "0=auto, 1=EC, 2=UCMS, 3=EC+NVRAM"); 8731 8135 8732 - module_param(brightness_enable, uint, 0); 8136 + module_param(brightness_enable, uint, 0444); 8733 8137 MODULE_PARM_DESC(brightness_enable, 8734 8138 "Enables backlight control when 1, disables when 0"); 8735 8139 8736 - module_param(hotkey_report_mode, uint, 0); 8140 + module_param(hotkey_report_mode, uint, 0444); 8737 8141 MODULE_PARM_DESC(hotkey_report_mode, 8738 8142 "used for backwards compatibility with userspace, " 8739 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"); 8740 8167 8741 8168 #define TPACPI_PARAM(feature) \ 8742 8169 module_param_call(feature, set_ibm_param, NULL, NULL, 0); \ ··· 8779 8160 TPACPI_PARAM(fan); 8780 8161 8781 8162 #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES 8782 - module_param(dbg_wlswemul, uint, 0); 8163 + module_param(dbg_wlswemul, uint, 0444); 8783 8164 MODULE_PARM_DESC(dbg_wlswemul, "Enables WLSW emulation"); 8784 8165 module_param_named(wlsw_state, tpacpi_wlsw_emulstate, bool, 0); 8785 8166 MODULE_PARM_DESC(wlsw_state, 8786 8167 "Initial state of the emulated WLSW switch"); 8787 8168 8788 - module_param(dbg_bluetoothemul, uint, 0); 8169 + module_param(dbg_bluetoothemul, uint, 0444); 8789 8170 MODULE_PARM_DESC(dbg_bluetoothemul, "Enables bluetooth switch emulation"); 8790 8171 module_param_named(bluetooth_state, tpacpi_bluetooth_emulstate, bool, 0); 8791 8172 MODULE_PARM_DESC(bluetooth_state, 8792 8173 "Initial state of the emulated bluetooth switch"); 8793 8174 8794 - module_param(dbg_wwanemul, uint, 0); 8175 + module_param(dbg_wwanemul, uint, 0444); 8795 8176 MODULE_PARM_DESC(dbg_wwanemul, "Enables WWAN switch emulation"); 8796 8177 module_param_named(wwan_state, tpacpi_wwan_emulstate, bool, 0); 8797 8178 MODULE_PARM_DESC(wwan_state, 8798 8179 "Initial state of the emulated WWAN switch"); 8799 8180 8800 - module_param(dbg_uwbemul, uint, 0); 8181 + module_param(dbg_uwbemul, uint, 0444); 8801 8182 MODULE_PARM_DESC(dbg_uwbemul, "Enables UWB switch emulation"); 8802 8183 module_param_named(uwb_state, tpacpi_uwb_emulstate, bool, 0); 8803 8184 MODULE_PARM_DESC(uwb_state, ··· 8990 8371 PCI_VENDOR_ID_IBM; 8991 8372 tpacpi_inputdev->id.product = TPACPI_HKEY_INPUT_PRODUCT; 8992 8373 tpacpi_inputdev->id.version = TPACPI_HKEY_INPUT_VERSION; 8374 + tpacpi_inputdev->dev.parent = &tpacpi_pdev->dev; 8993 8375 } 8994 8376 for (i = 0; i < ARRAY_SIZE(ibms_init); i++) { 8995 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 30 #include <linux/kernel.h> 31 31 #include <linux/init.h> 32 32 #include <linux/types.h> 33 + #include <linux/device.h> 33 34 #include <linux/list.h> 34 35 #include <linux/acpi.h> 35 36 #include <acpi/acpi_bus.h> ··· 66 65 acpi_handle handle; 67 66 wmi_notify_handler handler; 68 67 void *handler_data; 68 + struct device *dev; 69 69 }; 70 70 71 71 static struct wmi_block wmi_blocks; ··· 195 193 } 196 194 197 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; 198 224 } 199 225 200 226 static bool find_guid(const char *guid_string, struct wmi_block **out) ··· 585 555 EXPORT_SYMBOL_GPL(wmi_has_guid); 586 556 587 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 + /* 588 690 * Parse the _WDG method for the GUID data blocks 589 691 */ 590 692 static __init acpi_status parse_wdg(acpi_handle handle) ··· 871 709 872 710 if (result < 0) { 873 711 printk(KERN_INFO PREFIX "Error loading mapper\n"); 874 - } else { 875 - printk(KERN_INFO PREFIX "Mapper loaded\n"); 712 + return -ENODEV; 876 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"); 877 722 878 723 return result; 879 724 } ··· 889 720 { 890 721 struct list_head *p, *tmp; 891 722 struct wmi_block *wblock; 723 + 724 + wmi_class_exit(); 892 725 893 726 acpi_bus_unregister_driver(&acpi_wmi_driver); 894 727
+14 -6
drivers/pnp/pnpacpi/core.c
··· 80 80 81 81 static int pnpacpi_set_resources(struct pnp_dev *dev) 82 82 { 83 - acpi_handle handle = dev->data; 83 + struct acpi_device *acpi_dev = dev->data; 84 + acpi_handle handle = acpi_dev->handle; 84 85 struct acpi_buffer buffer; 85 86 int ret; 86 87 ··· 104 103 105 104 static int pnpacpi_disable_resources(struct pnp_dev *dev) 106 105 { 107 - acpi_handle handle = dev->data; 106 + struct acpi_device *acpi_dev = dev->data; 107 + acpi_handle handle = acpi_dev->handle; 108 108 int ret; 109 109 110 110 dev_dbg(&dev->dev, "disable resources\n"); ··· 123 121 #ifdef CONFIG_ACPI_SLEEP 124 122 static int pnpacpi_suspend(struct pnp_dev *dev, pm_message_t state) 125 123 { 124 + struct acpi_device *acpi_dev = dev->data; 125 + acpi_handle handle = acpi_dev->handle; 126 126 int power_state; 127 127 128 128 power_state = acpi_pm_device_sleep_state(&dev->dev, NULL); ··· 132 128 power_state = (state.event == PM_EVENT_ON) ? 133 129 ACPI_STATE_D0 : ACPI_STATE_D3; 134 130 135 - return acpi_bus_set_power((acpi_handle) dev->data, power_state); 131 + return acpi_bus_set_power(handle, power_state); 136 132 } 137 133 138 134 static int pnpacpi_resume(struct pnp_dev *dev) 139 135 { 140 - return acpi_bus_set_power((acpi_handle) dev->data, ACPI_STATE_D0); 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); 141 140 } 142 141 #endif 143 142 144 - static struct pnp_protocol pnpacpi_protocol = { 143 + struct pnp_protocol pnpacpi_protocol = { 145 144 .name = "Plug and Play ACPI", 146 145 .get = pnpacpi_get_resources, 147 146 .set = pnpacpi_set_resources, ··· 154 147 .resume = pnpacpi_resume, 155 148 #endif 156 149 }; 150 + EXPORT_SYMBOL(pnpacpi_protocol); 157 151 158 152 static int __init pnpacpi_add_device(struct acpi_device *device) 159 153 { ··· 176 168 if (!dev) 177 169 return -ENOMEM; 178 170 179 - dev->data = device->handle; 171 + dev->data = device; 180 172 /* .enabled means the device can decode the resources */ 181 173 dev->active = device->status.enabled; 182 174 status = acpi_get_handle(device->handle, "_SRS", &temp);
+6 -3
drivers/pnp/pnpacpi/rsparser.c
··· 465 465 466 466 int pnpacpi_parse_allocated_resource(struct pnp_dev *dev) 467 467 { 468 - acpi_handle handle = dev->data; 468 + struct acpi_device *acpi_dev = dev->data; 469 + acpi_handle handle = acpi_dev->handle; 469 470 acpi_status status; 470 471 471 472 pnp_dbg(&dev->dev, "parse allocated resources\n"); ··· 774 773 775 774 int __init pnpacpi_parse_resource_option_data(struct pnp_dev *dev) 776 775 { 777 - acpi_handle handle = dev->data; 776 + struct acpi_device *acpi_dev = dev->data; 777 + acpi_handle handle = acpi_dev->handle; 778 778 acpi_status status; 779 779 struct acpipnp_parse_option_s parse_data; 780 780 ··· 847 845 int pnpacpi_build_resource_template(struct pnp_dev *dev, 848 846 struct acpi_buffer *buffer) 849 847 { 850 - acpi_handle handle = dev->data; 848 + struct acpi_device *acpi_dev = dev->data; 849 + acpi_handle handle = acpi_dev->handle; 851 850 struct acpi_resource *resource; 852 851 int res_cnt = 0; 853 852 acpi_status status;
+12 -7
drivers/thermal/thermal_sys.c
··· 225 225 if (!sscanf(buf, "%d\n", &state)) 226 226 return -EINVAL; 227 227 228 + /* sanity check: values below 1000 millicelcius don't make sense 229 + * and can cause the system to go into a thermal heart attack 230 + */ 231 + if (state && state < 1000) 232 + return -EINVAL; 233 + 228 234 if (state && !tz->forced_passive) { 229 235 mutex_lock(&thermal_list_lock); 230 236 list_for_each_entry(cdev, &thermal_cdev_list, node) { ··· 241 235 cdev); 242 236 } 243 237 mutex_unlock(&thermal_list_lock); 238 + if (!tz->passive_delay) 239 + tz->passive_delay = 1000; 244 240 } else if (!state && tz->forced_passive) { 245 241 mutex_lock(&thermal_list_lock); 246 242 list_for_each_entry(cdev, &thermal_cdev_list, node) { ··· 253 245 cdev); 254 246 } 255 247 mutex_unlock(&thermal_list_lock); 248 + tz->passive_delay = 0; 256 249 } 257 250 258 251 tz->tc1 = 1; 259 252 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 253 267 254 tz->forced_passive = state; 268 255 ··· 377 374 if (!sscanf(buf, "%ld\n", &state)) 378 375 return -EINVAL; 379 376 380 - if (state < 0) 377 + if ((long)state < 0) 381 378 return -EINVAL; 382 379 383 380 result = cdev->ops->set_cur_state(cdev, state); ··· 1019 1016 thermal_zone_device_set_polling(tz, tz->passive_delay); 1020 1017 else if (tz->polling_delay) 1021 1018 thermal_zone_device_set_polling(tz, tz->polling_delay); 1019 + else 1020 + thermal_zone_device_set_polling(tz, 0); 1022 1021 mutex_unlock(&tz->lock); 1023 1022 } 1024 1023 EXPORT_SYMBOL(thermal_zone_device_update);
+5 -3
include/acpi/acoutput.h
··· 85 85 #define ACPI_LV_INIT 0x00000001 86 86 #define ACPI_LV_DEBUG_OBJECT 0x00000002 87 87 #define ACPI_LV_INFO 0x00000004 88 - #define ACPI_LV_ALL_EXCEPTIONS 0x00000007 88 + #define ACPI_LV_REPAIR 0x00000008 89 + #define ACPI_LV_ALL_EXCEPTIONS 0x0000000F 89 90 90 91 /* Trace verbosity level 1 [Standard Trace Level] */ 91 92 ··· 144 143 #define ACPI_DB_INIT ACPI_DEBUG_LEVEL (ACPI_LV_INIT) 145 144 #define ACPI_DB_DEBUG_OBJECT ACPI_DEBUG_LEVEL (ACPI_LV_DEBUG_OBJECT) 146 145 #define ACPI_DB_INFO ACPI_DEBUG_LEVEL (ACPI_LV_INFO) 146 + #define ACPI_DB_REPAIR ACPI_DEBUG_LEVEL (ACPI_LV_REPAIR) 147 147 #define ACPI_DB_ALL_EXCEPTIONS ACPI_DEBUG_LEVEL (ACPI_LV_ALL_EXCEPTIONS) 148 148 149 149 /* Trace level -- also used in the global "DebugLevel" */ ··· 176 174 177 175 /* Defaults for debug_level, debug and normal */ 178 176 179 - #define ACPI_DEBUG_DEFAULT (ACPI_LV_INFO) 180 - #define ACPI_NORMAL_DEFAULT (ACPI_LV_INIT | ACPI_LV_DEBUG_OBJECT) 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) 181 179 #define ACPI_DEBUG_ALL (ACPI_LV_AML_DISASSEMBLE | ACPI_LV_ALL_EXCEPTIONS | ACPI_LV_ALL) 182 180 183 181 #if defined (ACPI_DEBUG_OUTPUT) || !defined (ACPI_NO_ERROR_MESSAGES)
+1 -1
include/acpi/acpixf.h
··· 47 47 48 48 /* Current ACPICA subsystem version in YYYYMMDD format */ 49 49 50 - #define ACPI_CA_VERSION 0x20091112 50 + #define ACPI_CA_VERSION 0x20091214 51 51 52 52 #include "actypes.h" 53 53 #include "actbl.h"
+3 -2
include/acpi/processor.h
··· 294 294 #ifdef CONFIG_CPU_FREQ 295 295 void acpi_processor_ppc_init(void); 296 296 void acpi_processor_ppc_exit(void); 297 - int acpi_processor_ppc_has_changed(struct acpi_processor *pr); 297 + int acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag); 298 298 extern int acpi_processor_get_bios_limit(int cpu, unsigned int *limit); 299 299 #else 300 300 static inline void acpi_processor_ppc_init(void) ··· 305 305 { 306 306 return; 307 307 } 308 - static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr) 308 + static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr, 309 + int event_flag) 309 310 { 310 311 static unsigned int printout = 1; 311 312 if (printout) {
+20 -3
include/linux/acpi.h
··· 240 240 #define PXM_INVAL (-1) 241 241 #define NID_INVAL (-1) 242 242 243 - int acpi_check_resource_conflict(struct resource *res); 243 + int acpi_check_resource_conflict(const struct resource *res); 244 244 245 245 int acpi_check_region(resource_size_t start, resource_size_t n, 246 246 const char *name); ··· 253 253 void __init acpi_s4_no_nvs(void); 254 254 #endif /* CONFIG_PM_SLEEP */ 255 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 + 256 263 #define OSC_QUERY_TYPE 0 257 264 #define OSC_SUPPORT_TYPE 1 258 265 #define OSC_CONTROL_TYPE 2 259 - #define OSC_SUPPORT_MASKS 0x1f 260 266 261 267 /* _OSC DW0 Definition */ 262 268 #define OSC_QUERY_ENABLE 1 ··· 271 265 #define OSC_INVALID_REVISION_ERROR 8 272 266 #define OSC_CAPABILITIES_MASK_ERROR 16 273 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 */ 274 278 /* _OSC DW1 Definition (OS Support Fields) */ 275 279 #define OSC_EXT_PCI_CONFIG_SUPPORT 1 276 280 #define OSC_ACTIVE_STATE_PWR_SUPPORT 2 277 281 #define OSC_CLOCK_PWR_CAPABILITY_SUPPORT 4 278 282 #define OSC_PCI_SEGMENT_GROUPS_SUPPORT 8 279 283 #define OSC_MSI_SUPPORT 16 284 + #define OSC_PCI_SUPPORT_MASKS 0x1f 280 285 281 286 /* _OSC DW1 Definition (OS Control Fields) */ 282 287 #define OSC_PCI_EXPRESS_NATIVE_HP_CONTROL 1 ··· 296 279 #define OSC_PCI_EXPRESS_AER_CONTROL 8 297 280 #define OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL 16 298 281 299 - #define OSC_CONTROL_MASKS (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | \ 282 + #define OSC_PCI_CONTROL_MASKS (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | \ 300 283 OSC_SHPC_NATIVE_HP_CONTROL | \ 301 284 OSC_PCI_EXPRESS_PME_CONTROL | \ 302 285 OSC_PCI_EXPRESS_AER_CONTROL | \
+13
include/linux/pnp.h
··· 334 334 #define pnp_device_is_pnpbios(dev) 0 335 335 #endif 336 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 + 337 350 /* status */ 338 351 #define PNP_READY 0x0000 339 352 #define PNP_ATTACHED 0x0001