Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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: (77 commits)
ACPI: Populate /sys/firmware/acpi/tables/
ACPI: create CONFIG_ACPI_DEBUG_FUNC_TRACE
ACPI: update ACPI proc I/F removal schedule
ACPI: update feature-removal-schedule.txt, /sys/firmware/acpi/namespace is gone
ACPI: export ACPI events via acpi_mc_group multicast group
ACPI: fix empty macros found by -Wextra
ACPI: drivers/acpi/pci_link.c: lower printk severity
sony-laptop: Fix event reading in sony-laptop
sony-laptop: Add Vaio FE to the special init sequence
sony-laptop: Make the driver use MSC_SCAN and a setkeycode and getkeycode key table.
sony-laptop: Invoke _INI for SNC devices that provide it
sony-laptop: Add support for recent Vaios Fn keys (C series for now)
sony-laptop: map wireless switch events to KEY_WLAN
sony-laptop: add new SNC handlers
ACPI: thinkpad-acpi: add locking to brightness subdriver
ACPI: thinkpad-acpi: bump up version to 0.15
ACPI: thinkpad-acpi: make EC-based thermal readings non-experimental
ACPI: thinkpad-acpi: make sure DSDT TMPx readings don't return +128
ACPI: thinkpad-acpi: react to Lenovo ThinkPad differences in hot key
ACPI: thinkpad-acpi: allow use of CMOS NVRAM for brightness control
...

+2833 -864
+4 -17
Documentation/feature-removal-schedule.txt
··· 180 180 181 181 --------------------------- 182 182 183 - What: /sys/firmware/acpi/namespace 184 - When: 2.6.21 185 - Why: The ACPI namespace is effectively the symbol list for 186 - the BIOS. The device names are completely arbitrary 187 - and have no place being exposed to user-space. 188 - 189 - For those interested in the BIOS ACPI namespace, 190 - the BIOS can be extracted and disassembled with acpidump 191 - and iasl as documented in the pmtools package here: 192 - http://ftp.kernel.org/pub/linux/kernel/people/lenb/acpi/utils 193 - Who: Len Brown <len.brown@intel.com> 194 - 195 - --------------------------- 196 - 197 183 What: ACPI procfs interface 198 - When: July 2007 199 - Why: After ACPI sysfs conversion, ACPI attributes will be duplicated 200 - in sysfs and the ACPI procfs interface should be removed. 184 + When: July 2008 185 + Why: ACPI sysfs conversion should be finished by January 2008. 186 + ACPI procfs interface will be removed in July 2008 so that 187 + there is enough time for the user space to catch up. 201 188 Who: Zhang Rui <rui.zhang@intel.com> 202 189 203 190 ---------------------------
+271 -72
Documentation/thinkpad-acpi.txt
··· 1 1 ThinkPad ACPI Extras Driver 2 2 3 - Version 0.14 4 - April 21st, 2007 3 + Version 0.15 4 + July 1st, 2007 5 5 6 6 Borislav Deianov <borislav@users.sf.net> 7 - Henrique de Moraes Holschuh <hmh@hmh.eng.br> 8 - http://ibm-acpi.sf.net/ 7 + Henrique de Moraes Holschuh <hmh@hmh.eng.br> 8 + http://ibm-acpi.sf.net/ 9 9 10 10 11 11 This is a Linux driver for the IBM and Lenovo ThinkPad laptops. It ··· 134 134 subsystems are not documented here, nor are they tracked by this 135 135 attribute. 136 136 137 + Changes to the thinkpad-acpi sysfs interface are only considered 138 + non-experimental when they are submitted to Linux mainline, at which 139 + point the changes in this interface are documented and interface_version 140 + may be updated. If you are using any thinkpad-acpi features not yet 141 + sent to mainline for merging, you do so on your own risk: these features 142 + may disappear, or be implemented in a different and incompatible way by 143 + the time they are merged in Linux mainline. 144 + 145 + Changes that are backwards-compatible by nature (e.g. the addition of 146 + attributes that do not change the way the other attributes work) do not 147 + always warrant an update of interface_version. Therefore, one must 148 + expect that an attribute might not be there, and deal with it properly 149 + (an attribute not being there *is* a valid way to make it clear that a 150 + feature is not available in sysfs). 151 + 137 152 Hot keys 138 153 -------- 139 154 140 155 procfs: /proc/acpi/ibm/hotkey 141 156 sysfs device attribute: hotkey_* 142 157 143 - Without this driver, only the Fn-F4 key (sleep button) generates an 144 - ACPI event. With the driver loaded, the hotkey feature enabled and the 145 - mask set (see below), the various hot keys generate ACPI events in the 158 + In a ThinkPad, the ACPI HKEY handler is responsible for comunicating 159 + some important events and also keyboard hot key presses to the operating 160 + system. Enabling the hotkey functionality of thinkpad-acpi signals the 161 + firmware that such a driver is present, and modifies how the ThinkPad 162 + firmware will behave in many situations. 163 + 164 + When the hotkey feature is enabled and the hot key mask is set (see 165 + below), the various hot keys either generate ACPI events in the 146 166 following format: 147 167 148 168 ibm/hotkey HKEY 00000080 0000xxxx 149 169 150 - The last four digits vary depending on the key combination pressed. 151 - All labeled Fn-Fx key combinations generate distinct events. In 152 - addition, the lid microswitch and some docking station buttons may 153 - also generate such events. 170 + or events over the input layer. The input layer support accepts the 171 + standard IOCTLs to remap the keycodes assigned to each hotkey. 154 172 155 - The bit mask allows some control over which hot keys generate ACPI 156 - events. Not all bits in the mask can be modified. Not all bits that 157 - can be modified do anything. Not all hot keys can be individually 158 - controlled by the mask. Most recent ThinkPad models honor the 159 - following bits (assuming the hot keys feature has been enabled): 173 + When the input device is open, the driver will suppress any ACPI hot key 174 + events that get translated into a meaningful input layer event, in order 175 + to avoid sending duplicate events to userspace. Hot keys that are 176 + mapped to KEY_RESERVED in the keymap are not translated, and will always 177 + generate an ACPI ibm/hotkey HKEY event, and no input layer events. 160 178 161 - key bit behavior when set behavior when unset 179 + The hot key bit mask allows some control over which hot keys generate 180 + events. If a key is "masked" (bit set to 0 in the mask), the firmware 181 + will handle it. If it is "unmasked", it signals the firmware that 182 + thinkpad-acpi would prefer to handle it, if the firmware would be so 183 + kind to allow it (and it often doesn't!). 162 184 163 - Fn-F3 always generates ACPI event 164 - Fn-F4 always generates ACPI event 165 - Fn-F5 0010 generate ACPI event enable/disable Bluetooth 166 - Fn-F7 0040 generate ACPI event switch LCD and external display 167 - Fn-F8 0080 generate ACPI event expand screen or none 168 - Fn-F9 0100 generate ACPI event none 169 - Fn-F12 always generates ACPI event 185 + Not all bits in the mask can be modified. Not all bits that can be 186 + modified do anything. Not all hot keys can be individually controlled 187 + by the mask. Some models do not support the mask at all, and in those 188 + models, hot keys cannot be controlled individually. The behaviour of 189 + the mask is, therefore, higly dependent on the ThinkPad model. 170 190 171 - Some models do not support all of the above. For example, the T30 does 172 - not support Fn-F5 and Fn-F9. Other models do not support the mask at 173 - all. On those models, hot keys cannot be controlled individually. 191 + Note that unmasking some keys prevents their default behavior. For 192 + example, if Fn+F5 is unmasked, that key will no longer enable/disable 193 + Bluetooth by itself. 174 194 175 - Note that enabling ACPI events for some keys prevents their default 176 - behavior. For example, if events for Fn-F5 are enabled, that key will 177 - no longer enable/disable Bluetooth by itself. This can still be done 178 - from an acpid handler for the ibm/hotkey event. 179 - 180 - Note also that not all Fn key combinations are supported through 181 - ACPI. For example, on the X40, the brightness, volume and "Access IBM" 182 - buttons do not generate ACPI events even with this driver. They *can* 183 - be used through the "ThinkPad Buttons" utility, see 184 - http://www.nongnu.org/tpb/ 195 + Note also that not all Fn key combinations are supported through ACPI. 196 + For example, on the X40, the brightness, volume and "Access IBM" buttons 197 + do not generate ACPI events even with this driver. They *can* be used 198 + through the "ThinkPad Buttons" utility, see http://www.nongnu.org/tpb/ 185 199 186 200 procfs notes: 187 201 ··· 203 189 204 190 echo enable > /proc/acpi/ibm/hotkey -- enable the hot keys feature 205 191 echo disable > /proc/acpi/ibm/hotkey -- disable the hot keys feature 206 - echo 0xffff > /proc/acpi/ibm/hotkey -- enable all possible hot keys 207 - echo 0x0000 > /proc/acpi/ibm/hotkey -- disable all possible hot keys 208 - ... any other 4-hex-digit mask ... 192 + echo 0xffffffff > /proc/acpi/ibm/hotkey -- enable all hot keys 193 + echo 0 > /proc/acpi/ibm/hotkey -- disable all possible hot keys 194 + ... any other 8-hex-digit mask ... 209 195 echo reset > /proc/acpi/ibm/hotkey -- restore the original mask 210 196 211 197 sysfs notes: ··· 216 202 key feature status will be restored to this value. 217 203 218 204 0: hot keys were disabled 219 - 1: hot keys were enabled 205 + 1: hot keys were enabled (unusual) 220 206 221 207 hotkey_bios_mask: 222 208 Returns the hot keys mask when thinkpad-acpi was loaded. ··· 231 217 1: enables the hot keys feature / feature enabled 232 218 233 219 hotkey_mask: 234 - bit mask to enable ACPI event generation for each hot 235 - key (see above). Returns the current status of the hot 236 - keys mask, and allows one to modify it. 220 + bit mask to enable driver-handling and ACPI event 221 + generation for each hot key (see above). Returns the 222 + current status of the hot keys mask, and allows one to 223 + modify it. 224 + 225 + hotkey_all_mask: 226 + bit mask that should enable event reporting for all 227 + supported hot keys, when echoed to hotkey_mask above. 228 + Unless you know which events need to be handled 229 + passively (because the firmware *will* handle them 230 + anyway), do *not* use hotkey_all_mask. Use 231 + hotkey_recommended_mask, instead. You have been warned. 232 + 233 + hotkey_recommended_mask: 234 + bit mask that should enable event reporting for all 235 + supported hot keys, except those which are always 236 + handled by the firmware anyway. Echo it to 237 + hotkey_mask above, to use. 238 + 239 + hotkey_radio_sw: 240 + if the ThinkPad has a hardware radio switch, this 241 + attribute will read 0 if the switch is in the "radios 242 + disabled" postition, and 1 if the switch is in the 243 + "radios enabled" position. 244 + 245 + input layer notes: 246 + 247 + A Hot key is mapped to a single input layer EV_KEY event, possibly 248 + followed by an EV_MSC MSC_SCAN event that shall contain that key's scan 249 + code. An EV_SYN event will always be generated to mark the end of the 250 + event block. 251 + 252 + Do not use the EV_MSC MSC_SCAN events to process keys. They are to be 253 + used as a helper to remap keys, only. They are particularly useful when 254 + remapping KEY_UNKNOWN keys. 255 + 256 + The events are available in an input device, with the following id: 257 + 258 + Bus: BUS_HOST 259 + vendor: 0x1014 (PCI_VENDOR_ID_IBM) or 260 + 0x17aa (PCI_VENDOR_ID_LENOVO) 261 + product: 0x5054 ("TP") 262 + version: 0x4101 263 + 264 + The version will have its LSB incremented if the keymap changes in a 265 + backwards-compatible way. The MSB shall always be 0x41 for this input 266 + device. If the MSB is not 0x41, do not use the device as described in 267 + this section, as it is either something else (e.g. another input device 268 + exported by a thinkpad driver, such as HDAPS) or its functionality has 269 + been changed in a non-backwards compatible way. 270 + 271 + Adding other event types for other functionalities shall be considered a 272 + backwards-compatible change for this input device. 273 + 274 + Thinkpad-acpi Hot Key event map (version 0x4101): 275 + 276 + ACPI Scan 277 + event code Key Notes 278 + 279 + 0x1001 0x00 FN+F1 - 280 + 0x1002 0x01 FN+F2 IBM: battery (rare) 281 + Lenovo: Screen lock 282 + 283 + 0x1003 0x02 FN+F3 Many IBM models always report 284 + this hot key, even with hot keys 285 + disabled or with Fn+F3 masked 286 + off 287 + IBM: screen lock 288 + Lenovo: battery 289 + 290 + 0x1004 0x03 FN+F4 Sleep button (ACPI sleep button 291 + semanthics, i.e. sleep-to-RAM). 292 + It is always generate some kind 293 + of event, either the hot key 294 + event or a ACPI sleep button 295 + event. The firmware may 296 + refuse to generate further FN+F4 297 + key presses until a S3 or S4 ACPI 298 + sleep cycle is performed or some 299 + time passes. 300 + 301 + 0x1005 0x04 FN+F5 Radio. Enables/disables 302 + the internal BlueTooth hardware 303 + and W-WAN card if left in control 304 + of the firmware. Does not affect 305 + the WLAN card. 306 + Should be used to turn on/off all 307 + radios (bluetooth+W-WAN+WLAN), 308 + really. 309 + 310 + 0x1006 0x05 FN+F6 - 311 + 312 + 0x1007 0x06 FN+F7 Video output cycle. 313 + Do you feel lucky today? 314 + 315 + 0x1008 0x07 FN+F8 IBM: toggle screen expand 316 + Lenovo: configure ultranav 317 + 318 + 0x1009 0x08 FN+F9 - 319 + .. .. .. 320 + 0x100B 0x0A FN+F11 - 321 + 322 + 0x100C 0x0B FN+F12 Sleep to disk. You are always 323 + supposed to handle it yourself, 324 + either through the ACPI event, 325 + or through a hotkey event. 326 + The firmware may refuse to 327 + generate further FN+F4 key 328 + press events until a S3 or S4 329 + ACPI sleep cycle is performed, 330 + or some time passes. 331 + 332 + 0x100D 0x0C FN+BACKSPACE - 333 + 0x100E 0x0D FN+INSERT - 334 + 0x100F 0x0E FN+DELETE - 335 + 336 + 0x1010 0x0F FN+HOME Brightness up. This key is 337 + always handled by the firmware 338 + in IBM ThinkPads, even when 339 + unmasked. Just leave it alone. 340 + For Lenovo ThinkPads with a new 341 + BIOS, it has to be handled either 342 + by the ACPI OSI, or by userspace. 343 + 0x1011 0x10 FN+END Brightness down. See brightness 344 + up for details. 345 + 346 + 0x1012 0x11 FN+PGUP Thinklight toggle. This key is 347 + always handled by the firmware, 348 + even when unmasked. 349 + 350 + 0x1013 0x12 FN+PGDOWN - 351 + 352 + 0x1014 0x13 FN+SPACE Zoom key 353 + 354 + 0x1015 0x14 VOLUME UP Internal mixer volume up. This 355 + key is always handled by the 356 + firmware, even when unmasked. 357 + NOTE: Lenovo seems to be changing 358 + this. 359 + 0x1016 0x15 VOLUME DOWN Internal mixer volume up. This 360 + key is always handled by the 361 + firmware, even when unmasked. 362 + NOTE: Lenovo seems to be changing 363 + this. 364 + 0x1017 0x16 MUTE Mute internal mixer. This 365 + key is always handled by the 366 + firmware, even when unmasked. 367 + 368 + 0x1018 0x17 THINKPAD Thinkpad/Access IBM/Lenovo key 369 + 370 + 0x1019 0x18 unknown 371 + .. .. .. 372 + 0x1020 0x1F unknown 373 + 374 + The ThinkPad firmware does not allow one to differentiate when most hot 375 + keys are pressed or released (either that, or we don't know how to, yet). 376 + For these keys, the driver generates a set of events for a key press and 377 + immediately issues the same set of events for a key release. It is 378 + unknown by the driver if the ThinkPad firmware triggered these events on 379 + hot key press or release, but the firmware will do it for either one, not 380 + both. 381 + 382 + If a key is mapped to KEY_RESERVED, it generates no input events at all, 383 + and it may generate a legacy thinkpad-acpi ACPI hotkey event. 384 + 385 + If a key is mapped to KEY_UNKNOWN, it generates an input event that 386 + includes an scan code, and it may also generate a legacy thinkpad-acpi 387 + ACPI hotkey event. 388 + 389 + If a key is mapped to anything else, it will only generate legacy 390 + thinkpad-acpi ACPI hotkey events if nobody has opened the input device. 391 + 392 + Non hot-key ACPI HKEY event map: 393 + 0x5001 Lid closed 394 + 0x5002 Lid opened 395 + 0x7000 Radio Switch may have changed state 237 396 238 397 239 398 Bluetooth ··· 624 437 procfs: /proc/acpi/ibm/cmos 625 438 sysfs device attribute: cmos_command 626 439 627 - This feature is used internally by the ACPI firmware to control the 628 - ThinkLight on most newer ThinkPad models. It may also control LCD 629 - brightness, sounds volume and more, but only on some models. 440 + This feature is mostly used internally by the ACPI firmware to keep the legacy 441 + CMOS NVRAM bits in sync with the current machine state, and to record this 442 + state so that the ThinkPad will retain such settings across reboots. 443 + 444 + Some of these commands actually perform actions in some ThinkPad models, but 445 + this is expected to disappear more and more in newer models. As an example, in 446 + a T43 and in a X40, commands 12 and 13 still control the ThinkLight state for 447 + real, but commands 0 to 2 don't control the mixer anymore (they have been 448 + phased out) and just update the NVRAM. 630 449 631 450 The range of valid cmos command numbers is 0 to 21, but not all have an 632 451 effect and the behavior varies from model to model. Here is the behavior 633 452 on the X40 (tpb is the ThinkPad Buttons utility): 634 453 635 - 0 - no effect but tpb reports "Volume down" 636 - 1 - no effect but tpb reports "Volume up" 637 - 2 - no effect but tpb reports "Mute on" 638 - 3 - simulate pressing the "Access IBM" button 639 - 4 - LCD brightness up 640 - 5 - LCD brightness down 641 - 11 - toggle screen expansion 642 - 12 - ThinkLight on 643 - 13 - ThinkLight off 644 - 14 - no effect but tpb reports ThinkLight status change 454 + 0 - Related to "Volume down" key press 455 + 1 - Related to "Volume up" key press 456 + 2 - Related to "Mute on" key press 457 + 3 - Related to "Access IBM" key press 458 + 4 - Related to "LCD brightness up" key pess 459 + 5 - Related to "LCD brightness down" key press 460 + 11 - Related to "toggle screen expansion" key press/function 461 + 12 - Related to "ThinkLight on" 462 + 13 - Related to "ThinkLight off" 463 + 14 - Related to "ThinkLight" key press (toggle thinklight) 645 464 646 465 The cmos command interface is prone to firmware split-brain problems, as 647 - in newer ThinkPads it is just a compatibility layer. 466 + in newer ThinkPads it is just a compatibility layer. Do not use it, it is 467 + exported just as a debug tool. 648 468 649 469 LED control -- /proc/acpi/ibm/led 650 470 --------------------------------- ··· 710 516 procfs: /proc/acpi/ibm/thermal 711 517 sysfs device attributes: (hwmon) temp*_input 712 518 713 - Most ThinkPads include six or more separate temperature sensors but 714 - only expose the CPU temperature through the standard ACPI methods. 715 - This feature shows readings from up to eight different sensors on older 716 - ThinkPads, and it has experimental support for up to sixteen different 717 - sensors on newer ThinkPads. 718 - 719 - EXPERIMENTAL: The 16-sensors feature is marked EXPERIMENTAL because the 720 - implementation directly accesses hardware registers and may not work as 721 - expected. USE WITH CAUTION! To use this feature, you need to supply the 722 - experimental=1 parameter when loading the module. When EXPERIMENTAL 723 - mode is enabled, reading the first 8 sensors on newer ThinkPads will 724 - also use an new experimental thermal sensor access mode. 519 + Most ThinkPads include six or more separate temperature sensors but only 520 + expose the CPU temperature through the standard ACPI methods. This 521 + feature shows readings from up to eight different sensors on older 522 + ThinkPads, and up to sixteen different sensors on newer ThinkPads. 725 523 726 524 For example, on the X40, a typical output may be: 727 525 temperatures: 42 42 45 41 36 -128 33 -128 728 526 729 - EXPERIMENTAL: On the T43/p, a typical output may be: 527 + On the T43/p, a typical output may be: 730 528 temperatures: 48 48 36 52 38 -128 31 -128 48 52 48 -128 -128 -128 -128 -128 731 529 732 530 The mapping of thermal sensors to physical locations varies depending on ··· 748 562 2: System board, left side (near PCMCIA slot), reported as HDAPS temp 749 563 3: PCMCIA slot 750 564 9: MCH (northbridge) to DRAM Bus 751 - 10: ICH (southbridge), under Mini-PCI card, under touchpad 565 + 10: Clock-generator, mini-pci card and ICH (southbridge), under Mini-PCI 566 + card, under touchpad 752 567 11: Power regulator, underside of system board, below F2 key 753 568 754 569 The A31 has a very atypical layout for the thermal sensors ··· 867 680 868 681 The backlight control has eight levels, ranging from 0 to 7. Some of the 869 682 levels may not be distinct. 683 + 684 + There are two interfaces to the firmware for brightness control, EC and CMOS. 685 + To select which one should be used, use the brightness_mode module parameter: 686 + brightness_mode=1 selects EC mode, brightness_mode=2 selects CMOS mode, 687 + brightness_mode=3 selects both EC and CMOS. The driver tries to autodetect 688 + which interface to use. 870 689 871 690 Procfs notes: 872 691 ··· 1169 976 1170 977 0x000100: Initial sysfs support, as a single platform driver and 1171 978 device. 979 + 0x000200: Hot key support for 32 hot keys, and radio slider switch 980 + support. 981 + 0x010000: Hot keys are now handled by default over the input 982 + layer, the radio switch generates input event EV_RADIO, 983 + and the driver enables hot key handling by default in 984 + the firmware.
+3 -3
MAINTAINERS
··· 225 225 S: Supported 226 226 227 227 ACPI BATTERY DRIVERS 228 - P: Vladimir P. Lebedev 229 - M: vladimir.p.lebedev@intel.com 228 + P: Alexey Starikovskiy 229 + M: astarikovskiy@suse.de 230 230 L: linux-acpi@vger.kernel.org 231 231 W: http://acpi.sourceforge.net/ 232 232 S: Supported 233 233 234 234 ACPI EC DRIVER 235 235 P: Alexey Starikovskiy 236 - M: alexey.y.starikovskiy@linux.intel.com 236 + M: astarikovskiy@suse.de 237 237 L: linux-acpi@vger.kernel.org 238 238 W: http://acpi.sourceforge.net/ 239 239 S: Supported
-8
arch/i386/kernel/acpi/boot.c
··· 986 986 }, 987 987 { 988 988 .callback = force_acpi_ht, 989 - .ident = "DELL GX240", 990 - .matches = { 991 - DMI_MATCH(DMI_BOARD_VENDOR, "Dell Computer Corporation"), 992 - DMI_MATCH(DMI_BOARD_NAME, "OptiPlex GX240"), 993 - }, 994 - }, 995 - { 996 - .callback = force_acpi_ht, 997 989 .ident = "HP VISUALIZE NT Workstation", 998 990 .matches = { 999 991 DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
+2 -2
arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c
··· 665 665 data->max_freq = perf->states[0].core_frequency * 1000; 666 666 /* table init */ 667 667 for (i=0; i<perf->state_count; i++) { 668 - if (i>0 && perf->states[i].core_frequency == 669 - perf->states[i-1].core_frequency) 668 + if (i>0 && perf->states[i].core_frequency >= 669 + data->freq_table[valid_states-1].frequency / 1000) 670 670 continue; 671 671 672 672 data->freq_table[valid_states].index = i;
+11 -12
drivers/acpi/Kconfig
··· 2 2 # ACPI Configuration 3 3 # 4 4 5 - menu "ACPI (Advanced Configuration and Power Interface) Support" 5 + menuconfig ACPI 6 + bool "ACPI Support (Advanced Configuration and Power Interface) Support" 6 7 depends on !X86_NUMAQ 7 8 depends on !X86_VISWS 8 9 depends on !IA64_HP_SIM 9 - depends on IA64 || X86 10 - depends on PM 11 - 12 - config ACPI 13 - bool "ACPI Support" 14 10 depends on IA64 || X86 15 11 depends on PCI 16 12 depends on PM ··· 45 49 config ACPI_SLEEP 46 50 bool "Sleep States" 47 51 depends on X86 && (!SMP || SUSPEND_SMP) 48 - depends on PM 49 52 default y 50 53 ---help--- 51 54 This option adds support for ACPI suspend states. ··· 77 82 78 83 config ACPI_PROCFS 79 84 bool "Procfs interface (deprecated)" 80 - depends on ACPI 81 85 default y 82 86 ---help--- 83 87 The Procfs interface for ACPI is made optional for backward compatibility. ··· 118 124 119 125 config ACPI_VIDEO 120 126 tristate "Video" 121 - depends on X86 && BACKLIGHT_CLASS_DEVICE 127 + depends on X86 && BACKLIGHT_CLASS_DEVICE && VIDEO_OUTPUT_CONTROL 122 128 help 123 129 This driver implement the ACPI Extensions For Display Adapters 124 130 for integrated graphics devices on motherboard, as specified in ··· 274 280 of verbosity. Saying Y enables these statements. This will increase 275 281 your kernel size by around 50K. 276 282 283 + config ACPI_DEBUG_FUNC_TRACE 284 + bool "Additionally enable ACPI function tracing" 285 + default n 286 + depends on ACPI_DEBUG 287 + help 288 + ACPI Debug Statements slow down ACPI processing. Function trace 289 + is about half of the penalty and is rarely useful. 290 + 277 291 config ACPI_EC 278 292 bool 279 293 default y ··· 332 330 333 331 config ACPI_HOTPLUG_MEMORY 334 332 tristate "Memory Hotplug" 335 - depends on ACPI 336 333 depends on MEMORY_HOTPLUG 337 334 default n 338 335 help ··· 360 359 to today's ACPI "Control Method" battery. 361 360 362 361 endif # ACPI 363 - 364 - endmenu
+453 -250
drivers/acpi/battery.c
··· 43 43 #define ACPI_BATTERY_CLASS "battery" 44 44 #define ACPI_BATTERY_HID "PNP0C0A" 45 45 #define ACPI_BATTERY_DEVICE_NAME "Battery" 46 - #define ACPI_BATTERY_FILE_INFO "info" 47 - #define ACPI_BATTERY_FILE_STATUS "state" 48 - #define ACPI_BATTERY_FILE_ALARM "alarm" 49 46 #define ACPI_BATTERY_NOTIFY_STATUS 0x80 50 47 #define ACPI_BATTERY_NOTIFY_INFO 0x81 51 48 #define ACPI_BATTERY_UNITS_WATTS "mW" 52 49 #define ACPI_BATTERY_UNITS_AMPS "mA" 53 50 54 51 #define _COMPONENT ACPI_BATTERY_COMPONENT 52 + 53 + #define ACPI_BATTERY_UPDATE_TIME 0 54 + 55 + #define ACPI_BATTERY_NONE_UPDATE 0 56 + #define ACPI_BATTERY_EASY_UPDATE 1 57 + #define ACPI_BATTERY_INIT_UPDATE 2 58 + 55 59 ACPI_MODULE_NAME("battery"); 56 60 57 61 MODULE_AUTHOR("Paul Diefenbaugh"); 58 62 MODULE_DESCRIPTION("ACPI Battery Driver"); 59 63 MODULE_LICENSE("GPL"); 64 + 65 + static unsigned int update_time = ACPI_BATTERY_UPDATE_TIME; 66 + 67 + /* 0 - every time, > 0 - by update_time */ 68 + module_param(update_time, uint, 0644); 60 69 61 70 extern struct proc_dir_entry *acpi_lock_battery_dir(void); 62 71 extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); ··· 85 76 }, 86 77 }; 87 78 88 - struct acpi_battery_status { 79 + struct acpi_battery_state { 89 80 acpi_integer state; 90 81 acpi_integer present_rate; 91 82 acpi_integer remaining_capacity; ··· 108 99 acpi_string oem_info; 109 100 }; 110 101 111 - struct acpi_battery_flags { 112 - u8 present:1; /* Bay occupied? */ 113 - u8 power_unit:1; /* 0=watts, 1=apms */ 114 - u8 alarm:1; /* _BTP present? */ 115 - u8 reserved:5; 102 + enum acpi_battery_files{ 103 + ACPI_BATTERY_INFO = 0, 104 + ACPI_BATTERY_STATE, 105 + ACPI_BATTERY_ALARM, 106 + ACPI_BATTERY_NUMFILES, 116 107 }; 117 108 118 - struct acpi_battery_trips { 119 - unsigned long warning; 120 - unsigned long low; 109 + struct acpi_battery_flags { 110 + u8 battery_present_prev; 111 + u8 alarm_present; 112 + u8 init_update; 113 + u8 update[ACPI_BATTERY_NUMFILES]; 114 + u8 power_unit; 121 115 }; 122 116 123 117 struct acpi_battery { 124 - struct acpi_device * device; 118 + struct mutex mutex; 119 + struct acpi_device *device; 125 120 struct acpi_battery_flags flags; 126 - struct acpi_battery_trips trips; 121 + struct acpi_buffer bif_data; 122 + struct acpi_buffer bst_data; 127 123 unsigned long alarm; 128 - struct acpi_battery_info *info; 124 + unsigned long update_time[ACPI_BATTERY_NUMFILES]; 129 125 }; 126 + 127 + inline int acpi_battery_present(struct acpi_battery *battery) 128 + { 129 + return battery->device->status.battery_present; 130 + } 131 + inline char *acpi_battery_power_units(struct acpi_battery *battery) 132 + { 133 + if (battery->flags.power_unit) 134 + return ACPI_BATTERY_UNITS_AMPS; 135 + else 136 + return ACPI_BATTERY_UNITS_WATTS; 137 + } 138 + 139 + inline acpi_handle acpi_battery_handle(struct acpi_battery *battery) 140 + { 141 + return battery->device->handle; 142 + } 130 143 131 144 /* -------------------------------------------------------------------------- 132 145 Battery Management 133 146 -------------------------------------------------------------------------- */ 134 147 135 - static int 136 - acpi_battery_get_info(struct acpi_battery *battery, 137 - struct acpi_battery_info **bif) 148 + static void acpi_battery_check_result(struct acpi_battery *battery, int result) 149 + { 150 + if (!battery) 151 + return; 152 + 153 + if (result) { 154 + battery->flags.init_update = 1; 155 + } 156 + } 157 + 158 + static int acpi_battery_extract_package(struct acpi_battery *battery, 159 + union acpi_object *package, 160 + struct acpi_buffer *format, 161 + struct acpi_buffer *data, 162 + char *package_name) 163 + { 164 + acpi_status status = AE_OK; 165 + struct acpi_buffer data_null = { 0, NULL }; 166 + 167 + status = acpi_extract_package(package, format, &data_null); 168 + if (status != AE_BUFFER_OVERFLOW) { 169 + ACPI_EXCEPTION((AE_INFO, status, "Extracting size %s", 170 + package_name)); 171 + return -ENODEV; 172 + } 173 + 174 + if (data_null.length != data->length) { 175 + kfree(data->pointer); 176 + data->pointer = kzalloc(data_null.length, GFP_KERNEL); 177 + if (!data->pointer) { 178 + ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, "kzalloc()")); 179 + return -ENOMEM; 180 + } 181 + data->length = data_null.length; 182 + } 183 + 184 + status = acpi_extract_package(package, format, data); 185 + if (ACPI_FAILURE(status)) { 186 + ACPI_EXCEPTION((AE_INFO, status, "Extracting %s", 187 + package_name)); 188 + return -ENODEV; 189 + } 190 + 191 + return 0; 192 + } 193 + 194 + static int acpi_battery_get_status(struct acpi_battery *battery) 195 + { 196 + int result = 0; 197 + 198 + result = acpi_bus_get_status(battery->device); 199 + if (result) { 200 + ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Evaluating _STA")); 201 + return -ENODEV; 202 + } 203 + return result; 204 + } 205 + 206 + static int acpi_battery_get_info(struct acpi_battery *battery) 138 207 { 139 208 int result = 0; 140 209 acpi_status status = 0; ··· 220 133 struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BIF), 221 134 ACPI_BATTERY_FORMAT_BIF 222 135 }; 223 - struct acpi_buffer data = { 0, NULL }; 224 136 union acpi_object *package = NULL; 137 + struct acpi_buffer *data = NULL; 138 + struct acpi_battery_info *bif = NULL; 225 139 140 + battery->update_time[ACPI_BATTERY_INFO] = get_seconds(); 226 141 227 - if (!battery || !bif) 228 - return -EINVAL; 142 + if (!acpi_battery_present(battery)) 143 + return 0; 229 144 230 - /* Evalute _BIF */ 145 + /* Evaluate _BIF */ 231 146 232 - status = acpi_evaluate_object(battery->device->handle, "_BIF", NULL, &buffer); 147 + status = 148 + acpi_evaluate_object(acpi_battery_handle(battery), "_BIF", NULL, 149 + &buffer); 233 150 if (ACPI_FAILURE(status)) { 234 151 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF")); 235 152 return -ENODEV; ··· 241 150 242 151 package = buffer.pointer; 243 152 153 + data = &battery->bif_data; 154 + 244 155 /* Extract Package Data */ 245 156 246 - status = acpi_extract_package(package, &format, &data); 247 - if (status != AE_BUFFER_OVERFLOW) { 248 - ACPI_EXCEPTION((AE_INFO, status, "Extracting _BIF")); 249 - result = -ENODEV; 157 + result = 158 + acpi_battery_extract_package(battery, package, &format, data, 159 + "_BIF"); 160 + if (result) 250 161 goto end; 251 - } 252 - 253 - data.pointer = kzalloc(data.length, GFP_KERNEL); 254 - if (!data.pointer) { 255 - result = -ENOMEM; 256 - goto end; 257 - } 258 - 259 - status = acpi_extract_package(package, &format, &data); 260 - if (ACPI_FAILURE(status)) { 261 - ACPI_EXCEPTION((AE_INFO, status, "Extracting _BIF")); 262 - kfree(data.pointer); 263 - result = -ENODEV; 264 - goto end; 265 - } 266 162 267 163 end: 164 + 268 165 kfree(buffer.pointer); 269 166 270 - if (!result) 271 - (*bif) = data.pointer; 167 + if (!result) { 168 + bif = data->pointer; 169 + battery->flags.power_unit = bif->power_unit; 170 + } 272 171 273 172 return result; 274 173 } 275 174 276 - static int 277 - acpi_battery_get_status(struct acpi_battery *battery, 278 - struct acpi_battery_status **bst) 175 + static int acpi_battery_get_state(struct acpi_battery *battery) 279 176 { 280 177 int result = 0; 281 178 acpi_status status = 0; ··· 271 192 struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BST), 272 193 ACPI_BATTERY_FORMAT_BST 273 194 }; 274 - struct acpi_buffer data = { 0, NULL }; 275 195 union acpi_object *package = NULL; 196 + struct acpi_buffer *data = NULL; 276 197 198 + battery->update_time[ACPI_BATTERY_STATE] = get_seconds(); 277 199 278 - if (!battery || !bst) 279 - return -EINVAL; 200 + if (!acpi_battery_present(battery)) 201 + return 0; 280 202 281 - /* Evalute _BST */ 203 + /* Evaluate _BST */ 282 204 283 - status = acpi_evaluate_object(battery->device->handle, "_BST", NULL, &buffer); 205 + status = 206 + acpi_evaluate_object(acpi_battery_handle(battery), "_BST", NULL, 207 + &buffer); 284 208 if (ACPI_FAILURE(status)) { 285 209 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST")); 286 210 return -ENODEV; ··· 291 209 292 210 package = buffer.pointer; 293 211 212 + data = &battery->bst_data; 213 + 294 214 /* Extract Package Data */ 295 215 296 - status = acpi_extract_package(package, &format, &data); 297 - if (status != AE_BUFFER_OVERFLOW) { 298 - ACPI_EXCEPTION((AE_INFO, status, "Extracting _BST")); 299 - result = -ENODEV; 216 + result = 217 + acpi_battery_extract_package(battery, package, &format, data, 218 + "_BST"); 219 + if (result) 300 220 goto end; 301 - } 302 - 303 - data.pointer = kzalloc(data.length, GFP_KERNEL); 304 - if (!data.pointer) { 305 - result = -ENOMEM; 306 - goto end; 307 - } 308 - 309 - status = acpi_extract_package(package, &format, &data); 310 - if (ACPI_FAILURE(status)) { 311 - ACPI_EXCEPTION((AE_INFO, status, "Extracting _BST")); 312 - kfree(data.pointer); 313 - result = -ENODEV; 314 - goto end; 315 - } 316 221 317 222 end: 318 223 kfree(buffer.pointer); 319 224 320 - if (!result) 321 - (*bst) = data.pointer; 322 - 323 225 return result; 324 226 } 325 227 326 - static int 327 - acpi_battery_set_alarm(struct acpi_battery *battery, unsigned long alarm) 228 + static int acpi_battery_get_alarm(struct acpi_battery *battery) 229 + { 230 + battery->update_time[ACPI_BATTERY_ALARM] = get_seconds(); 231 + 232 + return 0; 233 + } 234 + 235 + static int acpi_battery_set_alarm(struct acpi_battery *battery, 236 + unsigned long alarm) 328 237 { 329 238 acpi_status status = 0; 330 239 union acpi_object arg0 = { ACPI_TYPE_INTEGER }; 331 240 struct acpi_object_list arg_list = { 1, &arg0 }; 332 241 242 + battery->update_time[ACPI_BATTERY_ALARM] = get_seconds(); 333 243 334 - if (!battery) 335 - return -EINVAL; 244 + if (!acpi_battery_present(battery)) 245 + return -ENODEV; 336 246 337 - if (!battery->flags.alarm) 247 + if (!battery->flags.alarm_present) 338 248 return -ENODEV; 339 249 340 250 arg0.integer.value = alarm; 341 251 342 - status = acpi_evaluate_object(battery->device->handle, "_BTP", &arg_list, NULL); 252 + status = 253 + acpi_evaluate_object(acpi_battery_handle(battery), "_BTP", 254 + &arg_list, NULL); 343 255 if (ACPI_FAILURE(status)) 344 256 return -ENODEV; 345 257 ··· 344 268 return 0; 345 269 } 346 270 347 - static int acpi_battery_check(struct acpi_battery *battery) 271 + static int acpi_battery_init_alarm(struct acpi_battery *battery) 348 272 { 349 273 int result = 0; 350 274 acpi_status status = AE_OK; 351 275 acpi_handle handle = NULL; 352 - struct acpi_device *device = NULL; 353 - struct acpi_battery_info *bif = NULL; 276 + struct acpi_battery_info *bif = battery->bif_data.pointer; 277 + unsigned long alarm = battery->alarm; 354 278 279 + /* See if alarms are supported, and if so, set default */ 355 280 356 - if (!battery) 357 - return -EINVAL; 358 - 359 - device = battery->device; 360 - 361 - result = acpi_bus_get_status(device); 362 - if (result) 363 - return result; 364 - 365 - /* Insertion? */ 366 - 367 - if (!battery->flags.present && device->status.battery_present) { 368 - 369 - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery inserted\n")); 370 - 371 - /* Evalute _BIF to get certain static information */ 372 - 373 - result = acpi_battery_get_info(battery, &bif); 374 - if (result) 375 - return result; 376 - 377 - battery->flags.power_unit = bif->power_unit; 378 - battery->trips.warning = bif->design_capacity_warning; 379 - battery->trips.low = bif->design_capacity_low; 380 - kfree(bif); 381 - 382 - /* See if alarms are supported, and if so, set default */ 383 - 384 - status = acpi_get_handle(battery->device->handle, "_BTP", &handle); 385 - if (ACPI_SUCCESS(status)) { 386 - battery->flags.alarm = 1; 387 - acpi_battery_set_alarm(battery, battery->trips.warning); 281 + status = acpi_get_handle(acpi_battery_handle(battery), "_BTP", &handle); 282 + if (ACPI_SUCCESS(status)) { 283 + battery->flags.alarm_present = 1; 284 + if (!alarm && bif) { 285 + alarm = bif->design_capacity_warning; 388 286 } 287 + result = acpi_battery_set_alarm(battery, alarm); 288 + if (result) 289 + goto end; 290 + } else { 291 + battery->flags.alarm_present = 0; 389 292 } 390 293 391 - /* Removal? */ 392 - 393 - else if (battery->flags.present && !device->status.battery_present) { 394 - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery removed\n")); 395 - } 396 - 397 - battery->flags.present = device->status.battery_present; 294 + end: 398 295 399 296 return result; 400 297 } 401 298 402 - static void acpi_battery_check_present(struct acpi_battery *battery) 299 + static int acpi_battery_init_update(struct acpi_battery *battery) 403 300 { 404 - if (!battery->flags.present) { 405 - acpi_battery_check(battery); 301 + int result = 0; 302 + 303 + result = acpi_battery_get_status(battery); 304 + if (result) 305 + return result; 306 + 307 + battery->flags.battery_present_prev = acpi_battery_present(battery); 308 + 309 + if (acpi_battery_present(battery)) { 310 + result = acpi_battery_get_info(battery); 311 + if (result) 312 + return result; 313 + result = acpi_battery_get_state(battery); 314 + if (result) 315 + return result; 316 + 317 + acpi_battery_init_alarm(battery); 318 + } 319 + 320 + return result; 321 + } 322 + 323 + static int acpi_battery_update(struct acpi_battery *battery, 324 + int update, int *update_result_ptr) 325 + { 326 + int result = 0; 327 + int update_result = ACPI_BATTERY_NONE_UPDATE; 328 + 329 + if (!acpi_battery_present(battery)) { 330 + update = 1; 331 + } 332 + 333 + if (battery->flags.init_update) { 334 + result = acpi_battery_init_update(battery); 335 + if (result) 336 + goto end; 337 + update_result = ACPI_BATTERY_INIT_UPDATE; 338 + } else if (update) { 339 + result = acpi_battery_get_status(battery); 340 + if (result) 341 + goto end; 342 + if ((!battery->flags.battery_present_prev & acpi_battery_present(battery)) 343 + || (battery->flags.battery_present_prev & !acpi_battery_present(battery))) { 344 + result = acpi_battery_init_update(battery); 345 + if (result) 346 + goto end; 347 + update_result = ACPI_BATTERY_INIT_UPDATE; 348 + } else { 349 + update_result = ACPI_BATTERY_EASY_UPDATE; 350 + } 351 + } 352 + 353 + end: 354 + 355 + battery->flags.init_update = (result != 0); 356 + 357 + *update_result_ptr = update_result; 358 + 359 + return result; 360 + } 361 + 362 + static void acpi_battery_notify_update(struct acpi_battery *battery) 363 + { 364 + acpi_battery_get_status(battery); 365 + 366 + if (battery->flags.init_update) { 367 + return; 368 + } 369 + 370 + if ((!battery->flags.battery_present_prev & 371 + acpi_battery_present(battery)) || 372 + (battery->flags.battery_present_prev & 373 + !acpi_battery_present(battery))) { 374 + battery->flags.init_update = 1; 375 + } else { 376 + battery->flags.update[ACPI_BATTERY_INFO] = 1; 377 + battery->flags.update[ACPI_BATTERY_STATE] = 1; 378 + battery->flags.update[ACPI_BATTERY_ALARM] = 1; 406 379 } 407 380 } 408 381 ··· 460 335 -------------------------------------------------------------------------- */ 461 336 462 337 static struct proc_dir_entry *acpi_battery_dir; 463 - static int acpi_battery_read_info(struct seq_file *seq, void *offset) 338 + 339 + static int acpi_battery_print_info(struct seq_file *seq, int result) 464 340 { 465 - int result = 0; 466 341 struct acpi_battery *battery = seq->private; 467 342 struct acpi_battery_info *bif = NULL; 468 343 char *units = "?"; 469 344 470 - 471 - if (!battery) 345 + if (result) 472 346 goto end; 473 347 474 - acpi_battery_check_present(battery); 475 - 476 - if (battery->flags.present) 348 + if (acpi_battery_present(battery)) 477 349 seq_printf(seq, "present: yes\n"); 478 350 else { 479 351 seq_printf(seq, "present: no\n"); 480 352 goto end; 481 353 } 482 354 483 - /* Battery Info (_BIF) */ 484 - 485 - result = acpi_battery_get_info(battery, &bif); 486 - if (result || !bif) { 487 - seq_printf(seq, "ERROR: Unable to read battery information\n"); 355 + bif = battery->bif_data.pointer; 356 + if (!bif) { 357 + ACPI_EXCEPTION((AE_INFO, AE_ERROR, "BIF buffer is NULL")); 358 + result = -ENODEV; 488 359 goto end; 489 360 } 490 361 491 - units = 492 - bif-> 493 - power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS; 362 + /* Battery Units */ 363 + 364 + units = acpi_battery_power_units(battery); 494 365 495 366 if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN) 496 367 seq_printf(seq, "design capacity: unknown\n"); ··· 517 396 else 518 397 seq_printf(seq, "design voltage: %d mV\n", 519 398 (u32) bif->design_voltage); 520 - 521 399 seq_printf(seq, "design capacity warning: %d %sh\n", 522 400 (u32) bif->design_capacity_warning, units); 523 401 seq_printf(seq, "design capacity low: %d %sh\n", ··· 531 411 seq_printf(seq, "OEM info: %s\n", bif->oem_info); 532 412 533 413 end: 534 - kfree(bif); 535 414 536 - return 0; 415 + if (result) 416 + seq_printf(seq, "ERROR: Unable to read battery info\n"); 417 + 418 + return result; 537 419 } 538 420 539 - static int acpi_battery_info_open_fs(struct inode *inode, struct file *file) 421 + static int acpi_battery_print_state(struct seq_file *seq, int result) 540 422 { 541 - return single_open(file, acpi_battery_read_info, PDE(inode)->data); 542 - } 543 - 544 - static int acpi_battery_read_state(struct seq_file *seq, void *offset) 545 - { 546 - int result = 0; 547 423 struct acpi_battery *battery = seq->private; 548 - struct acpi_battery_status *bst = NULL; 424 + struct acpi_battery_state *bst = NULL; 549 425 char *units = "?"; 550 426 551 - 552 - if (!battery) 427 + if (result) 553 428 goto end; 554 429 555 - acpi_battery_check_present(battery); 556 - 557 - if (battery->flags.present) 430 + if (acpi_battery_present(battery)) 558 431 seq_printf(seq, "present: yes\n"); 559 432 else { 560 433 seq_printf(seq, "present: no\n"); 561 434 goto end; 562 435 } 563 436 564 - /* Battery Units */ 565 - 566 - units = 567 - battery->flags. 568 - power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS; 569 - 570 - /* Battery Status (_BST) */ 571 - 572 - result = acpi_battery_get_status(battery, &bst); 573 - if (result || !bst) { 574 - seq_printf(seq, "ERROR: Unable to read battery status\n"); 437 + bst = battery->bst_data.pointer; 438 + if (!bst) { 439 + ACPI_EXCEPTION((AE_INFO, AE_ERROR, "BST buffer is NULL")); 440 + result = -ENODEV; 575 441 goto end; 576 442 } 443 + 444 + /* Battery Units */ 445 + 446 + units = acpi_battery_power_units(battery); 577 447 578 448 if (!(bst->state & 0x04)) 579 449 seq_printf(seq, "capacity state: ok\n"); ··· 600 490 (u32) bst->present_voltage); 601 491 602 492 end: 603 - kfree(bst); 604 493 605 - return 0; 494 + if (result) { 495 + seq_printf(seq, "ERROR: Unable to read battery state\n"); 496 + } 497 + 498 + return result; 606 499 } 607 500 608 - static int acpi_battery_state_open_fs(struct inode *inode, struct file *file) 609 - { 610 - return single_open(file, acpi_battery_read_state, PDE(inode)->data); 611 - } 612 - 613 - static int acpi_battery_read_alarm(struct seq_file *seq, void *offset) 501 + static int acpi_battery_print_alarm(struct seq_file *seq, int result) 614 502 { 615 503 struct acpi_battery *battery = seq->private; 616 504 char *units = "?"; 617 505 618 - 619 - if (!battery) 506 + if (result) 620 507 goto end; 621 508 622 - acpi_battery_check_present(battery); 623 - 624 - if (!battery->flags.present) { 509 + if (!acpi_battery_present(battery)) { 625 510 seq_printf(seq, "present: no\n"); 626 511 goto end; 627 512 } 628 513 629 514 /* Battery Units */ 630 515 631 - units = 632 - battery->flags. 633 - power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS; 634 - 635 - /* Battery Alarm */ 516 + units = acpi_battery_power_units(battery); 636 517 637 518 seq_printf(seq, "alarm: "); 638 519 if (!battery->alarm) 639 520 seq_printf(seq, "unsupported\n"); 640 521 else 641 - seq_printf(seq, "%d %sh\n", (u32) battery->alarm, units); 522 + seq_printf(seq, "%lu %sh\n", battery->alarm, units); 642 523 643 524 end: 644 - return 0; 525 + 526 + if (result) 527 + seq_printf(seq, "ERROR: Unable to read battery alarm\n"); 528 + 529 + return result; 645 530 } 646 531 647 532 static ssize_t ··· 648 543 char alarm_string[12] = { '\0' }; 649 544 struct seq_file *m = file->private_data; 650 545 struct acpi_battery *battery = m->private; 651 - 546 + int update_result = ACPI_BATTERY_NONE_UPDATE; 652 547 653 548 if (!battery || (count > sizeof(alarm_string) - 1)) 654 549 return -EINVAL; 655 550 656 - acpi_battery_check_present(battery); 551 + mutex_lock(&battery->mutex); 657 552 658 - if (!battery->flags.present) 659 - return -ENODEV; 553 + result = acpi_battery_update(battery, 1, &update_result); 554 + if (result) { 555 + result = -ENODEV; 556 + goto end; 557 + } 660 558 661 - if (copy_from_user(alarm_string, buffer, count)) 662 - return -EFAULT; 559 + if (!acpi_battery_present(battery)) { 560 + result = -ENODEV; 561 + goto end; 562 + } 563 + 564 + if (copy_from_user(alarm_string, buffer, count)) { 565 + result = -EFAULT; 566 + goto end; 567 + } 663 568 664 569 alarm_string[count] = '\0'; 665 570 666 571 result = acpi_battery_set_alarm(battery, 667 572 simple_strtoul(alarm_string, NULL, 0)); 668 573 if (result) 669 - return result; 574 + goto end; 670 575 671 - return count; 576 + end: 577 + 578 + acpi_battery_check_result(battery, result); 579 + 580 + if (!result) 581 + result = count; 582 + 583 + mutex_unlock(&battery->mutex); 584 + 585 + return result; 586 + } 587 + 588 + typedef int(*print_func)(struct seq_file *seq, int result); 589 + typedef int(*get_func)(struct acpi_battery *battery); 590 + 591 + static struct acpi_read_mux { 592 + print_func print; 593 + get_func get; 594 + } acpi_read_funcs[ACPI_BATTERY_NUMFILES] = { 595 + {.get = acpi_battery_get_info, .print = acpi_battery_print_info}, 596 + {.get = acpi_battery_get_state, .print = acpi_battery_print_state}, 597 + {.get = acpi_battery_get_alarm, .print = acpi_battery_print_alarm}, 598 + }; 599 + 600 + static int acpi_battery_read(int fid, struct seq_file *seq) 601 + { 602 + struct acpi_battery *battery = seq->private; 603 + int result = 0; 604 + int update_result = ACPI_BATTERY_NONE_UPDATE; 605 + int update = 0; 606 + 607 + mutex_lock(&battery->mutex); 608 + 609 + update = (get_seconds() - battery->update_time[fid] >= update_time); 610 + update = (update | battery->flags.update[fid]); 611 + 612 + result = acpi_battery_update(battery, update, &update_result); 613 + if (result) 614 + goto end; 615 + 616 + if (update_result == ACPI_BATTERY_EASY_UPDATE) { 617 + result = acpi_read_funcs[fid].get(battery); 618 + if (result) 619 + goto end; 620 + } 621 + 622 + end: 623 + result = acpi_read_funcs[fid].print(seq, result); 624 + acpi_battery_check_result(battery, result); 625 + battery->flags.update[fid] = result; 626 + mutex_unlock(&battery->mutex); 627 + return result; 628 + } 629 + 630 + static int acpi_battery_read_info(struct seq_file *seq, void *offset) 631 + { 632 + return acpi_battery_read(ACPI_BATTERY_INFO, seq); 633 + } 634 + 635 + static int acpi_battery_read_state(struct seq_file *seq, void *offset) 636 + { 637 + return acpi_battery_read(ACPI_BATTERY_STATE, seq); 638 + } 639 + 640 + static int acpi_battery_read_alarm(struct seq_file *seq, void *offset) 641 + { 642 + return acpi_battery_read(ACPI_BATTERY_ALARM, seq); 643 + } 644 + 645 + static int acpi_battery_info_open_fs(struct inode *inode, struct file *file) 646 + { 647 + return single_open(file, acpi_battery_read_info, PDE(inode)->data); 648 + } 649 + 650 + static int acpi_battery_state_open_fs(struct inode *inode, struct file *file) 651 + { 652 + return single_open(file, acpi_battery_read_state, PDE(inode)->data); 672 653 } 673 654 674 655 static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file) ··· 762 571 return single_open(file, acpi_battery_read_alarm, PDE(inode)->data); 763 572 } 764 573 765 - static const struct file_operations acpi_battery_info_ops = { 574 + static struct battery_file { 575 + struct file_operations ops; 576 + mode_t mode; 577 + char *name; 578 + } acpi_battery_file[] = { 579 + { 580 + .name = "info", 581 + .mode = S_IRUGO, 582 + .ops = { 766 583 .open = acpi_battery_info_open_fs, 767 584 .read = seq_read, 768 585 .llseek = seq_lseek, 769 586 .release = single_release, 770 587 .owner = THIS_MODULE, 771 - }; 772 - 773 - static const struct file_operations acpi_battery_state_ops = { 588 + }, 589 + }, 590 + { 591 + .name = "state", 592 + .mode = S_IRUGO, 593 + .ops = { 774 594 .open = acpi_battery_state_open_fs, 775 595 .read = seq_read, 776 596 .llseek = seq_lseek, 777 597 .release = single_release, 778 598 .owner = THIS_MODULE, 779 - }; 780 - 781 - static const struct file_operations acpi_battery_alarm_ops = { 599 + }, 600 + }, 601 + { 602 + .name = "alarm", 603 + .mode = S_IFREG | S_IRUGO | S_IWUSR, 604 + .ops = { 782 605 .open = acpi_battery_alarm_open_fs, 783 606 .read = seq_read, 784 607 .write = acpi_battery_write_alarm, 785 608 .llseek = seq_lseek, 786 609 .release = single_release, 787 610 .owner = THIS_MODULE, 611 + }, 612 + }, 788 613 }; 789 614 790 615 static int acpi_battery_add_fs(struct acpi_device *device) 791 616 { 792 617 struct proc_dir_entry *entry = NULL; 793 - 618 + int i; 794 619 795 620 if (!acpi_device_dir(device)) { 796 621 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), ··· 816 609 acpi_device_dir(device)->owner = THIS_MODULE; 817 610 } 818 611 819 - /* 'info' [R] */ 820 - entry = create_proc_entry(ACPI_BATTERY_FILE_INFO, 821 - S_IRUGO, acpi_device_dir(device)); 822 - if (!entry) 823 - return -ENODEV; 824 - else { 825 - entry->proc_fops = &acpi_battery_info_ops; 826 - entry->data = acpi_driver_data(device); 827 - entry->owner = THIS_MODULE; 828 - } 829 - 830 - /* 'status' [R] */ 831 - entry = create_proc_entry(ACPI_BATTERY_FILE_STATUS, 832 - S_IRUGO, acpi_device_dir(device)); 833 - if (!entry) 834 - return -ENODEV; 835 - else { 836 - entry->proc_fops = &acpi_battery_state_ops; 837 - entry->data = acpi_driver_data(device); 838 - entry->owner = THIS_MODULE; 839 - } 840 - 841 - /* 'alarm' [R/W] */ 842 - entry = create_proc_entry(ACPI_BATTERY_FILE_ALARM, 843 - S_IFREG | S_IRUGO | S_IWUSR, 844 - acpi_device_dir(device)); 845 - if (!entry) 846 - return -ENODEV; 847 - else { 848 - entry->proc_fops = &acpi_battery_alarm_ops; 849 - entry->data = acpi_driver_data(device); 850 - entry->owner = THIS_MODULE; 612 + for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) { 613 + entry = create_proc_entry(acpi_battery_file[i].name, 614 + acpi_battery_file[i].mode, acpi_device_dir(device)); 615 + if (!entry) 616 + return -ENODEV; 617 + else { 618 + entry->proc_fops = &acpi_battery_file[i].ops; 619 + entry->data = acpi_driver_data(device); 620 + entry->owner = THIS_MODULE; 621 + } 851 622 } 852 623 853 624 return 0; ··· 833 648 834 649 static int acpi_battery_remove_fs(struct acpi_device *device) 835 650 { 836 - 651 + int i; 837 652 if (acpi_device_dir(device)) { 838 - remove_proc_entry(ACPI_BATTERY_FILE_ALARM, 653 + for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) { 654 + remove_proc_entry(acpi_battery_file[i].name, 839 655 acpi_device_dir(device)); 840 - remove_proc_entry(ACPI_BATTERY_FILE_STATUS, 841 - acpi_device_dir(device)); 842 - remove_proc_entry(ACPI_BATTERY_FILE_INFO, 843 - acpi_device_dir(device)); 844 - 656 + } 845 657 remove_proc_entry(acpi_device_bid(device), acpi_battery_dir); 846 658 acpi_device_dir(device) = NULL; 847 659 } ··· 855 673 struct acpi_battery *battery = data; 856 674 struct acpi_device *device = NULL; 857 675 858 - 859 676 if (!battery) 860 677 return; 861 678 ··· 865 684 case ACPI_BATTERY_NOTIFY_INFO: 866 685 case ACPI_NOTIFY_BUS_CHECK: 867 686 case ACPI_NOTIFY_DEVICE_CHECK: 868 - acpi_battery_check(battery); 869 - acpi_bus_generate_event(device, event, battery->flags.present); 687 + device = battery->device; 688 + acpi_battery_notify_update(battery); 689 + acpi_bus_generate_event(device, event, 690 + acpi_battery_present(battery)); 870 691 break; 871 692 default: 872 693 ACPI_DEBUG_PRINT((ACPI_DB_INFO, ··· 885 702 acpi_status status = 0; 886 703 struct acpi_battery *battery = NULL; 887 704 888 - 889 705 if (!device) 890 706 return -EINVAL; 891 707 ··· 892 710 if (!battery) 893 711 return -ENOMEM; 894 712 713 + mutex_init(&battery->mutex); 714 + 715 + mutex_lock(&battery->mutex); 716 + 895 717 battery->device = device; 896 718 strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME); 897 719 strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS); 898 720 acpi_driver_data(device) = battery; 899 721 900 - result = acpi_battery_check(battery); 722 + result = acpi_battery_get_status(battery); 901 723 if (result) 902 724 goto end; 725 + 726 + battery->flags.init_update = 1; 903 727 904 728 result = acpi_battery_add_fs(device); 905 729 if (result) ··· 915 727 ACPI_ALL_NOTIFY, 916 728 acpi_battery_notify, battery); 917 729 if (ACPI_FAILURE(status)) { 730 + ACPI_EXCEPTION((AE_INFO, status, "Installing notify handler")); 918 731 result = -ENODEV; 919 732 goto end; 920 733 } ··· 925 736 device->status.battery_present ? "present" : "absent"); 926 737 927 738 end: 739 + 928 740 if (result) { 929 741 acpi_battery_remove_fs(device); 930 742 kfree(battery); 931 743 } 744 + 745 + mutex_unlock(&battery->mutex); 932 746 933 747 return result; 934 748 } ··· 941 749 acpi_status status = 0; 942 750 struct acpi_battery *battery = NULL; 943 751 944 - 945 752 if (!device || !acpi_driver_data(device)) 946 753 return -EINVAL; 947 754 948 755 battery = acpi_driver_data(device); 756 + 757 + mutex_lock(&battery->mutex); 949 758 950 759 status = acpi_remove_notify_handler(device->handle, 951 760 ACPI_ALL_NOTIFY, 952 761 acpi_battery_notify); 953 762 954 763 acpi_battery_remove_fs(device); 764 + 765 + kfree(battery->bif_data.pointer); 766 + 767 + kfree(battery->bst_data.pointer); 768 + 769 + mutex_unlock(&battery->mutex); 770 + 771 + mutex_destroy(&battery->mutex); 955 772 956 773 kfree(battery); 957 774 ··· 976 775 return -EINVAL; 977 776 978 777 battery = device->driver_data; 979 - return acpi_battery_check(battery); 778 + 779 + battery->flags.init_update = 1; 780 + 781 + return 0; 980 782 } 981 783 982 784 static int __init acpi_battery_init(void) ··· 1004 800 1005 801 static void __exit acpi_battery_exit(void) 1006 802 { 1007 - 1008 803 acpi_bus_unregister_driver(&acpi_battery_driver); 1009 804 1010 805 acpi_unlock_battery_dir(acpi_battery_dir);
+9 -10
drivers/acpi/bay.c
··· 288 288 new_bay->pdev = pdev; 289 289 platform_set_drvdata(pdev, new_bay); 290 290 291 + /* 292 + * we want the bay driver to be able to send uevents 293 + */ 294 + pdev->dev.uevent_suppress = 0; 295 + 291 296 if (acpi_bay_add_fs(new_bay)) { 292 297 platform_device_unregister(new_bay->pdev); 293 298 goto bay_add_err; ··· 333 328 { 334 329 struct bay *bay_dev = (struct bay *)data; 335 330 struct device *dev = &bay_dev->pdev->dev; 331 + char event_string[12]; 332 + char *envp[] = { event_string, NULL }; 336 333 337 334 bay_dprintk(handle, "Bay event"); 338 - 339 - switch(event) { 340 - case ACPI_NOTIFY_BUS_CHECK: 341 - case ACPI_NOTIFY_DEVICE_CHECK: 342 - case ACPI_NOTIFY_EJECT_REQUEST: 343 - kobject_uevent(&dev->kobj, KOBJ_CHANGE); 344 - break; 345 - default: 346 - printk(KERN_ERR PREFIX "Bay: unknown event %d\n", event); 347 - } 335 + sprintf(event_string, "BAY_EVENT=%d\n", event); 336 + kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); 348 337 } 349 338 350 339 static acpi_status
+4
drivers/acpi/bus.c
··· 292 292 if (!device) 293 293 return -EINVAL; 294 294 295 + if (acpi_bus_generate_genetlink_event(device, type, data)) 296 + printk(KERN_WARNING PREFIX 297 + "Failed to generate an ACPI event via genetlink!\n"); 298 + 295 299 /* drop event on the floor if no one's listening */ 296 300 if (!event_is_open) 297 301 return 0;
+99 -32
drivers/acpi/dock.c
··· 40 40 MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_DESCRIPTION); 41 41 MODULE_LICENSE("GPL"); 42 42 43 + static int immediate_undock = 1; 44 + module_param(immediate_undock, bool, 0644); 45 + MODULE_PARM_DESC(immediate_undock, "1 (default) will cause the driver to " 46 + "undock immediately when the undock button is pressed, 0 will cause" 47 + " the driver to wait for userspace to write the undock sysfs file " 48 + " before undocking"); 49 + 43 50 static struct atomic_notifier_head dock_notifier_list; 44 - static struct platform_device dock_device; 51 + static struct platform_device *dock_device; 45 52 static char dock_device_name[] = "dock"; 46 53 47 54 struct dock_station { ··· 70 63 }; 71 64 72 65 #define DOCK_DOCKING 0x00000001 66 + #define DOCK_UNDOCKING 0x00000002 73 67 #define DOCK_EVENT 3 74 68 #define UNDOCK_EVENT 2 75 69 ··· 335 327 336 328 static void dock_event(struct dock_station *ds, u32 event, int num) 337 329 { 338 - struct device *dev = &dock_device.dev; 330 + struct device *dev = &dock_device->dev; 331 + char event_string[7]; 332 + char *envp[] = { event_string, NULL }; 333 + 334 + if (num == UNDOCK_EVENT) 335 + sprintf(event_string, "UNDOCK"); 336 + else 337 + sprintf(event_string, "DOCK"); 338 + 339 339 /* 340 340 * Indicate that the status of the dock station has 341 341 * changed. 342 342 */ 343 - kobject_uevent(&dev->kobj, KOBJ_CHANGE); 343 + kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); 344 344 } 345 345 346 346 /** ··· 396 380 union acpi_object arg; 397 381 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 398 382 struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 399 - union acpi_object *obj; 400 383 401 384 acpi_get_name(ds->handle, ACPI_FULL_PATHNAME, &name_buffer); 402 - obj = name_buffer.pointer; 403 385 404 - printk(KERN_INFO PREFIX "%s\n", dock ? "docking" : "undocking"); 386 + printk(KERN_INFO PREFIX "%s - %s\n", 387 + (char *)name_buffer.pointer, dock ? "docking" : "undocking"); 405 388 406 389 /* _DCK method has one argument */ 407 390 arg_list.count = 1; ··· 409 394 arg.integer.value = dock; 410 395 status = acpi_evaluate_object(ds->handle, "_DCK", &arg_list, &buffer); 411 396 if (ACPI_FAILURE(status)) 412 - pr_debug("%s: failed to execute _DCK\n", obj->string.pointer); 397 + printk(KERN_ERR PREFIX "%s - failed to execute _DCK\n", 398 + (char *)name_buffer.pointer); 413 399 kfree(buffer.pointer); 414 400 kfree(name_buffer.pointer); 415 401 } ··· 434 418 { 435 419 ds->flags &= ~(DOCK_DOCKING); 436 420 ds->last_dock_time = jiffies; 421 + } 422 + 423 + static inline void begin_undock(struct dock_station *ds) 424 + { 425 + ds->flags |= DOCK_UNDOCKING; 426 + } 427 + 428 + static inline void complete_undock(struct dock_station *ds) 429 + { 430 + ds->flags &= ~(DOCK_UNDOCKING); 437 431 } 438 432 439 433 /** ··· 576 550 printk(KERN_ERR PREFIX "Unable to undock!\n"); 577 551 return -EBUSY; 578 552 } 579 - 553 + complete_undock(ds); 580 554 return 0; 581 555 } 582 556 ··· 620 594 * to the driver who wish to hotplug. 621 595 */ 622 596 case ACPI_NOTIFY_EJECT_REQUEST: 623 - handle_eject_request(ds, event); 597 + begin_undock(ds); 598 + if (immediate_undock) 599 + handle_eject_request(ds, event); 600 + else 601 + dock_event(ds, event, UNDOCK_EVENT); 624 602 break; 625 603 default: 626 604 printk(KERN_ERR PREFIX "Unknown dock event %d\n", event); ··· 683 653 DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL); 684 654 685 655 /* 656 + * show_flags - read method for flags file in sysfs 657 + */ 658 + static ssize_t show_flags(struct device *dev, 659 + struct device_attribute *attr, char *buf) 660 + { 661 + return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags); 662 + 663 + } 664 + DEVICE_ATTR(flags, S_IRUGO, show_flags, NULL); 665 + 666 + /* 686 667 * write_undock - write method for "undock" file in sysfs 687 668 */ 688 669 static ssize_t write_undock(struct device *dev, struct device_attribute *attr, ··· 716 675 struct device_attribute *attr, char *buf) 717 676 { 718 677 unsigned long lbuf; 719 - acpi_status status = acpi_evaluate_integer(dock_station->handle, "_UID", NULL, &lbuf); 720 - if(ACPI_FAILURE(status)) { 678 + acpi_status status = acpi_evaluate_integer(dock_station->handle, 679 + "_UID", NULL, &lbuf); 680 + if (ACPI_FAILURE(status)) 721 681 return 0; 722 - } 682 + 723 683 return snprintf(buf, PAGE_SIZE, "%lx\n", lbuf); 724 684 } 725 685 DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL); 726 - 727 - 728 686 729 687 /** 730 688 * dock_add - add a new dock station ··· 751 711 ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list); 752 712 753 713 /* initialize platform device stuff */ 754 - dock_device.name = dock_device_name; 755 - ret = platform_device_register(&dock_device); 756 - if (ret) { 757 - printk(KERN_ERR PREFIX "Error %d registering dock device\n", ret); 714 + dock_device = 715 + platform_device_register_simple(dock_device_name, 0, NULL, 0); 716 + if (IS_ERR(dock_device)) { 758 717 kfree(dock_station); 759 - return ret; 718 + dock_station = NULL; 719 + return PTR_ERR(dock_device); 760 720 } 761 - ret = device_create_file(&dock_device.dev, &dev_attr_docked); 721 + 722 + /* we want the dock device to send uevents */ 723 + dock_device->dev.uevent_suppress = 0; 724 + 725 + ret = device_create_file(&dock_device->dev, &dev_attr_docked); 762 726 if (ret) { 763 727 printk("Error %d adding sysfs file\n", ret); 764 - platform_device_unregister(&dock_device); 728 + platform_device_unregister(dock_device); 765 729 kfree(dock_station); 730 + dock_station = NULL; 766 731 return ret; 767 732 } 768 - ret = device_create_file(&dock_device.dev, &dev_attr_undock); 733 + ret = device_create_file(&dock_device->dev, &dev_attr_undock); 769 734 if (ret) { 770 735 printk("Error %d adding sysfs file\n", ret); 771 - device_remove_file(&dock_device.dev, &dev_attr_docked); 772 - platform_device_unregister(&dock_device); 736 + device_remove_file(&dock_device->dev, &dev_attr_docked); 737 + platform_device_unregister(dock_device); 773 738 kfree(dock_station); 739 + dock_station = NULL; 774 740 return ret; 775 741 } 776 - ret = device_create_file(&dock_device.dev, &dev_attr_uid); 742 + ret = device_create_file(&dock_device->dev, &dev_attr_uid); 777 743 if (ret) { 778 744 printk("Error %d adding sysfs file\n", ret); 779 - platform_device_unregister(&dock_device); 745 + device_remove_file(&dock_device->dev, &dev_attr_docked); 746 + device_remove_file(&dock_device->dev, &dev_attr_undock); 747 + platform_device_unregister(dock_device); 780 748 kfree(dock_station); 749 + dock_station = NULL; 750 + return ret; 751 + } 752 + ret = device_create_file(&dock_device->dev, &dev_attr_flags); 753 + if (ret) { 754 + printk("Error %d adding sysfs file\n", ret); 755 + device_remove_file(&dock_device->dev, &dev_attr_docked); 756 + device_remove_file(&dock_device->dev, &dev_attr_undock); 757 + device_remove_file(&dock_device->dev, &dev_attr_uid); 758 + platform_device_unregister(dock_device); 759 + kfree(dock_station); 760 + dock_station = NULL; 781 761 return ret; 782 762 } 783 763 ··· 810 750 dd = alloc_dock_dependent_device(handle); 811 751 if (!dd) { 812 752 kfree(dock_station); 753 + dock_station = NULL; 813 754 ret = -ENOMEM; 814 755 goto dock_add_err_unregister; 815 756 } ··· 834 773 dock_add_err: 835 774 kfree(dd); 836 775 dock_add_err_unregister: 837 - device_remove_file(&dock_device.dev, &dev_attr_docked); 838 - device_remove_file(&dock_device.dev, &dev_attr_undock); 839 - platform_device_unregister(&dock_device); 776 + device_remove_file(&dock_device->dev, &dev_attr_docked); 777 + device_remove_file(&dock_device->dev, &dev_attr_undock); 778 + device_remove_file(&dock_device->dev, &dev_attr_uid); 779 + device_remove_file(&dock_device->dev, &dev_attr_flags); 780 + platform_device_unregister(dock_device); 840 781 kfree(dock_station); 782 + dock_station = NULL; 841 783 return ret; 842 784 } 843 785 ··· 868 804 printk(KERN_ERR "Error removing notify handler\n"); 869 805 870 806 /* cleanup sysfs */ 871 - device_remove_file(&dock_device.dev, &dev_attr_docked); 872 - device_remove_file(&dock_device.dev, &dev_attr_undock); 873 - platform_device_unregister(&dock_device); 807 + device_remove_file(&dock_device->dev, &dev_attr_docked); 808 + device_remove_file(&dock_device->dev, &dev_attr_undock); 809 + device_remove_file(&dock_device->dev, &dev_attr_uid); 810 + device_remove_file(&dock_device->dev, &dev_attr_flags); 811 + platform_device_unregister(dock_device); 874 812 875 813 /* free dock station memory */ 876 814 kfree(dock_station); 815 + dock_station = NULL; 877 816 return 0; 878 817 } 879 818
+148 -103
drivers/acpi/ec.c
··· 34 34 #include <linux/proc_fs.h> 35 35 #include <linux/seq_file.h> 36 36 #include <linux/interrupt.h> 37 + #include <linux/list.h> 37 38 #include <asm/io.h> 38 39 #include <acpi/acpi_bus.h> 39 40 #include <acpi/acpi_drivers.h> 40 41 #include <acpi/actypes.h> 41 42 42 - #define _COMPONENT ACPI_EC_COMPONENT 43 - ACPI_MODULE_NAME("ec"); 44 - #define ACPI_EC_COMPONENT 0x00100000 45 43 #define ACPI_EC_CLASS "embedded_controller" 46 44 #define ACPI_EC_HID "PNP0C09" 47 45 #define ACPI_EC_DEVICE_NAME "Embedded Controller" 48 46 #define ACPI_EC_FILE_INFO "info" 47 + 49 48 #undef PREFIX 50 49 #define PREFIX "ACPI: EC: " 50 + 51 51 /* EC status register */ 52 52 #define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ 53 53 #define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ 54 54 #define ACPI_EC_FLAG_BURST 0x10 /* burst mode */ 55 55 #define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */ 56 + 56 57 /* EC commands */ 57 58 enum ec_command { 58 59 ACPI_EC_COMMAND_READ = 0x80, ··· 62 61 ACPI_EC_BURST_DISABLE = 0x83, 63 62 ACPI_EC_COMMAND_QUERY = 0x84, 64 63 }; 64 + 65 65 /* EC events */ 66 66 enum ec_event { 67 67 ACPI_EC_EVENT_OBF_1 = 1, /* Output buffer full */ ··· 96 94 97 95 /* If we find an EC via the ECDT, we need to keep a ptr to its context */ 98 96 /* External interfaces use first EC only, so remember */ 97 + typedef int (*acpi_ec_query_func) (void *data); 98 + 99 + struct acpi_ec_query_handler { 100 + struct list_head node; 101 + acpi_ec_query_func func; 102 + acpi_handle handle; 103 + void *data; 104 + u8 query_bit; 105 + }; 106 + 99 107 static struct acpi_ec { 100 108 acpi_handle handle; 101 109 unsigned long gpe; ··· 116 104 atomic_t query_pending; 117 105 atomic_t event_count; 118 106 wait_queue_head_t wait; 107 + struct list_head list; 119 108 } *boot_ec, *first_ec; 120 109 121 110 /* -------------------------------------------------------------------------- ··· 258 245 259 246 status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0, 0); 260 247 if (status) { 261 - printk(KERN_DEBUG PREFIX 248 + printk(KERN_ERR PREFIX 262 249 "input buffer is not empty, aborting transaction\n"); 263 250 goto end; 264 251 } ··· 407 394 /* -------------------------------------------------------------------------- 408 395 Event Management 409 396 -------------------------------------------------------------------------- */ 397 + int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit, 398 + acpi_handle handle, acpi_ec_query_func func, 399 + void *data) 400 + { 401 + struct acpi_ec_query_handler *handler = 402 + kzalloc(sizeof(struct acpi_ec_query_handler), GFP_KERNEL); 403 + if (!handler) 404 + return -ENOMEM; 405 + 406 + handler->query_bit = query_bit; 407 + handler->handle = handle; 408 + handler->func = func; 409 + handler->data = data; 410 + mutex_lock(&ec->lock); 411 + list_add_tail(&handler->node, &ec->list); 412 + mutex_unlock(&ec->lock); 413 + return 0; 414 + } 415 + 416 + EXPORT_SYMBOL_GPL(acpi_ec_add_query_handler); 417 + 418 + void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit) 419 + { 420 + struct acpi_ec_query_handler *handler; 421 + mutex_lock(&ec->lock); 422 + list_for_each_entry(handler, &ec->list, node) { 423 + if (query_bit == handler->query_bit) { 424 + list_del(&handler->node); 425 + kfree(handler); 426 + break; 427 + } 428 + } 429 + mutex_unlock(&ec->lock); 430 + } 431 + 432 + EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler); 410 433 411 434 static void acpi_ec_gpe_query(void *ec_cxt) 412 435 { 413 436 struct acpi_ec *ec = ec_cxt; 414 437 u8 value = 0; 415 - char object_name[8]; 438 + struct acpi_ec_query_handler *handler, copy; 416 439 417 440 if (!ec || acpi_ec_query(ec, &value)) 418 441 return; 419 - 420 - snprintf(object_name, 8, "_Q%2.2X", value); 421 - 422 - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s", object_name)); 423 - 424 - acpi_evaluate_object(ec->handle, object_name, NULL, NULL); 442 + mutex_lock(&ec->lock); 443 + list_for_each_entry(handler, &ec->list, node) { 444 + if (value == handler->query_bit) { 445 + /* have custom handler for this bit */ 446 + memcpy(&copy, handler, sizeof(copy)); 447 + mutex_unlock(&ec->lock); 448 + if (copy.func) { 449 + copy.func(copy.data); 450 + } else if (copy.handle) { 451 + acpi_evaluate_object(copy.handle, NULL, NULL, NULL); 452 + } 453 + return; 454 + } 455 + } 456 + mutex_unlock(&ec->lock); 457 + printk(KERN_ERR PREFIX "Handler for query 0x%x is not found!\n", value); 425 458 } 426 459 427 460 static u32 acpi_ec_gpe_handler(void *data) ··· 486 427 if ((value & ACPI_EC_FLAG_SCI) && !atomic_read(&ec->query_pending)) { 487 428 atomic_set(&ec->query_pending, 1); 488 429 status = 489 - acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, 490 - ec); 430 + acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, ec); 491 431 } 492 432 493 433 return status == AE_OK ? ··· 512 454 } 513 455 514 456 static acpi_status 515 - acpi_ec_space_handler(u32 function, 516 - acpi_physical_address address, 517 - u32 bit_width, 518 - acpi_integer * value, 457 + acpi_ec_space_handler(u32 function, acpi_physical_address address, 458 + u32 bits, acpi_integer *value, 519 459 void *handler_context, void *region_context) 520 460 { 521 - int result = 0; 522 461 struct acpi_ec *ec = handler_context; 523 - u64 temp = *value; 524 - acpi_integer f_v = 0; 525 - int i = 0; 462 + int result = 0, i = 0; 463 + u8 temp = 0; 526 464 527 465 if ((address > 0xFF) || !value || !handler_context) 528 466 return AE_BAD_PARAMETER; 529 467 530 - if (bit_width != 8 && acpi_strict) { 468 + if (function != ACPI_READ && function != ACPI_WRITE) 531 469 return AE_BAD_PARAMETER; 470 + 471 + if (bits != 8 && acpi_strict) 472 + return AE_BAD_PARAMETER; 473 + 474 + while (bits - i > 0) { 475 + if (function == ACPI_READ) { 476 + result = acpi_ec_read(ec, address, &temp); 477 + (*value) |= ((acpi_integer)temp) << i; 478 + } else { 479 + temp = 0xff & ((*value) >> i); 480 + result = acpi_ec_write(ec, address, temp); 481 + } 482 + i += 8; 483 + ++address; 532 484 } 533 485 534 - next_byte: 535 - switch (function) { 536 - case ACPI_READ: 537 - temp = 0; 538 - result = acpi_ec_read(ec, (u8) address, (u8 *) & temp); 539 - break; 540 - case ACPI_WRITE: 541 - result = acpi_ec_write(ec, (u8) address, (u8) temp); 542 - break; 543 - default: 544 - result = -EINVAL; 545 - goto out; 546 - break; 547 - } 548 - 549 - bit_width -= 8; 550 - if (bit_width) { 551 - if (function == ACPI_READ) 552 - f_v |= temp << 8 * i; 553 - if (function == ACPI_WRITE) 554 - temp >>= 8; 555 - i++; 556 - address++; 557 - goto next_byte; 558 - } 559 - 560 - if (function == ACPI_READ) { 561 - f_v |= temp << 8 * i; 562 - *value = f_v; 563 - } 564 - 565 - out: 566 486 switch (result) { 567 487 case -EINVAL: 568 488 return AE_BAD_PARAMETER; ··· 633 597 static acpi_status 634 598 ec_parse_io_ports(struct acpi_resource *resource, void *context); 635 599 636 - static acpi_status 637 - ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval); 638 - 639 600 static struct acpi_ec *make_acpi_ec(void) 640 601 { 641 602 struct acpi_ec *ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL); ··· 643 610 atomic_set(&ec->event_count, 1); 644 611 mutex_init(&ec->lock); 645 612 init_waitqueue_head(&ec->wait); 613 + INIT_LIST_HEAD(&ec->list); 646 614 647 615 return ec; 648 616 } 649 617 618 + static acpi_status 619 + acpi_ec_register_query_methods(acpi_handle handle, u32 level, 620 + void *context, void **return_value) 621 + { 622 + struct acpi_namespace_node *node = handle; 623 + struct acpi_ec *ec = context; 624 + int value = 0; 625 + if (sscanf(node->name.ascii, "_Q%x", &value) == 1) { 626 + acpi_ec_add_query_handler(ec, value, handle, NULL, NULL); 627 + } 628 + return AE_OK; 629 + } 630 + 631 + static int ec_parse_device(struct acpi_ec *ec, acpi_handle handle) 632 + { 633 + if (ACPI_FAILURE(acpi_walk_resources(handle, METHOD_NAME__CRS, 634 + ec_parse_io_ports, ec))) 635 + return -EINVAL; 636 + 637 + /* Get GPE bit assignment (EC events). */ 638 + /* TODO: Add support for _GPE returning a package */ 639 + if (ACPI_FAILURE(acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe))) 640 + return -EINVAL; 641 + 642 + /* Use the global lock for all EC transactions? */ 643 + acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock); 644 + 645 + /* Find and register all query methods */ 646 + acpi_walk_namespace(ACPI_TYPE_METHOD, handle, 1, 647 + acpi_ec_register_query_methods, ec, NULL); 648 + 649 + ec->handle = handle; 650 + 651 + printk(KERN_INFO PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx", 652 + ec->gpe, ec->command_addr, ec->data_addr); 653 + 654 + return 0; 655 + } 656 + 650 657 static int acpi_ec_add(struct acpi_device *device) 651 658 { 652 - acpi_status status = AE_OK; 653 659 struct acpi_ec *ec = NULL; 654 660 655 661 if (!device) ··· 701 629 if (!ec) 702 630 return -ENOMEM; 703 631 704 - status = ec_parse_device(device->handle, 0, ec, NULL); 705 - if (status != AE_CTRL_TERMINATE) { 632 + if (ec_parse_device(ec, device->handle)) { 706 633 kfree(ec); 707 634 return -EINVAL; 708 635 } ··· 712 641 /* We might have incorrect info for GL at boot time */ 713 642 mutex_lock(&boot_ec->lock); 714 643 boot_ec->global_lock = ec->global_lock; 644 + /* Copy handlers from new ec into boot ec */ 645 + list_splice(&ec->list, &boot_ec->list); 715 646 mutex_unlock(&boot_ec->lock); 716 647 kfree(ec); 717 648 ec = boot_ec; ··· 724 651 acpi_driver_data(device) = ec; 725 652 726 653 acpi_ec_add_fs(device); 727 - 728 - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s [%s] (gpe %d) interrupt mode.", 729 - acpi_device_name(device), acpi_device_bid(device), 730 - (u32) ec->gpe)); 731 - 732 654 return 0; 733 655 } 734 656 735 657 static int acpi_ec_remove(struct acpi_device *device, int type) 736 658 { 737 659 struct acpi_ec *ec; 660 + struct acpi_ec_query_handler *handler; 738 661 739 662 if (!device) 740 663 return -EINVAL; 741 664 742 665 ec = acpi_driver_data(device); 666 + mutex_lock(&ec->lock); 667 + list_for_each_entry(handler, &ec->list, node) { 668 + list_del(&handler->node); 669 + kfree(handler); 670 + } 671 + mutex_unlock(&ec->lock); 743 672 acpi_ec_remove_fs(device); 744 673 acpi_driver_data(device) = NULL; 745 674 if (ec == first_ec) ··· 797 722 return -ENODEV; 798 723 } 799 724 800 - /* EC is fully operational, allow queries */ 801 - atomic_set(&ec->query_pending, 0); 802 - 803 725 return 0; 804 726 } 805 727 806 728 static int acpi_ec_start(struct acpi_device *device) 807 729 { 808 730 struct acpi_ec *ec; 731 + int ret = 0; 809 732 810 733 if (!device) 811 734 return -EINVAL; ··· 813 740 if (!ec) 814 741 return -EINVAL; 815 742 816 - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02lx, ports=0x%2lx,0x%2lx", 817 - ec->gpe, ec->command_addr, ec->data_addr)); 818 - 819 743 /* Boot EC is already working */ 820 - if (ec == boot_ec) 821 - return 0; 744 + if (ec != boot_ec) 745 + ret = ec_install_handlers(ec); 822 746 823 - return ec_install_handlers(ec); 747 + /* EC is fully operational, allow queries */ 748 + atomic_set(&ec->query_pending, 0); 749 + 750 + return ret; 824 751 } 825 752 826 753 static int acpi_ec_stop(struct acpi_device *device, int type) ··· 852 779 return 0; 853 780 } 854 781 855 - static acpi_status 856 - ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval) 857 - { 858 - acpi_status status; 859 - 860 - struct acpi_ec *ec = context; 861 - status = acpi_walk_resources(handle, METHOD_NAME__CRS, 862 - ec_parse_io_ports, ec); 863 - if (ACPI_FAILURE(status)) 864 - return status; 865 - 866 - /* Get GPE bit assignment (EC events). */ 867 - /* TODO: Add support for _GPE returning a package */ 868 - status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe); 869 - if (ACPI_FAILURE(status)) 870 - return status; 871 - 872 - /* Use the global lock for all EC transactions? */ 873 - acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock); 874 - 875 - ec->handle = handle; 876 - 877 - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "GPE=0x%02lx, ports=0x%2lx, 0x%2lx", 878 - ec->gpe, ec->command_addr, ec->data_addr)); 879 - 880 - return AE_CTRL_TERMINATE; 881 - } 882 - 883 782 int __init acpi_ec_ecdt_probe(void) 884 783 { 885 784 int ret; ··· 870 825 if (ACPI_FAILURE(status)) 871 826 goto error; 872 827 873 - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found ECDT")); 828 + printk(KERN_INFO PREFIX "EC description table is found, configuring boot EC\n"); 874 829 875 830 boot_ec->command_addr = ecdt_ptr->control.address; 876 831 boot_ec->data_addr = ecdt_ptr->data.address;
+146 -7
drivers/acpi/event.c
··· 11 11 #include <linux/init.h> 12 12 #include <linux/poll.h> 13 13 #include <acpi/acpi_drivers.h> 14 + #include <net/netlink.h> 15 + #include <net/genetlink.h> 14 16 15 17 #define _COMPONENT ACPI_SYSTEM_COMPONENT 16 18 ACPI_MODULE_NAME("event"); ··· 49 47 static char str[ACPI_MAX_STRING]; 50 48 static int chars_remaining = 0; 51 49 static char *ptr; 52 - 53 50 54 51 if (!chars_remaining) { 55 52 memset(&event, 0, sizeof(struct acpi_bus_event)); ··· 107 106 .poll = acpi_system_poll_event, 108 107 }; 109 108 109 + #ifdef CONFIG_NET 110 + unsigned int acpi_event_seqnum; 111 + struct acpi_genl_event { 112 + acpi_device_class device_class; 113 + char bus_id[15]; 114 + u32 type; 115 + u32 data; 116 + }; 117 + 118 + /* attributes of acpi_genl_family */ 119 + enum { 120 + ACPI_GENL_ATTR_UNSPEC, 121 + ACPI_GENL_ATTR_EVENT, /* ACPI event info needed by user space */ 122 + __ACPI_GENL_ATTR_MAX, 123 + }; 124 + #define ACPI_GENL_ATTR_MAX (__ACPI_GENL_ATTR_MAX - 1) 125 + 126 + /* commands supported by the acpi_genl_family */ 127 + enum { 128 + ACPI_GENL_CMD_UNSPEC, 129 + ACPI_GENL_CMD_EVENT, /* kernel->user notifications for ACPI events */ 130 + __ACPI_GENL_CMD_MAX, 131 + }; 132 + #define ACPI_GENL_CMD_MAX (__ACPI_GENL_CMD_MAX - 1) 133 + 134 + #define ACPI_GENL_FAMILY_NAME "acpi_event" 135 + #define ACPI_GENL_VERSION 0x01 136 + #define ACPI_GENL_MCAST_GROUP_NAME "acpi_mc_group" 137 + 138 + static struct genl_family acpi_event_genl_family = { 139 + .id = GENL_ID_GENERATE, 140 + .name = ACPI_GENL_FAMILY_NAME, 141 + .version = ACPI_GENL_VERSION, 142 + .maxattr = ACPI_GENL_ATTR_MAX, 143 + }; 144 + 145 + static struct genl_multicast_group acpi_event_mcgrp = { 146 + .name = ACPI_GENL_MCAST_GROUP_NAME, 147 + }; 148 + 149 + int acpi_bus_generate_genetlink_event(struct acpi_device *device, 150 + u8 type, int data) 151 + { 152 + struct sk_buff *skb; 153 + struct nlattr *attr; 154 + struct acpi_genl_event *event; 155 + void *msg_header; 156 + int size; 157 + int result; 158 + 159 + /* allocate memory */ 160 + size = nla_total_size(sizeof(struct acpi_genl_event)) + 161 + nla_total_size(0); 162 + 163 + skb = genlmsg_new(size, GFP_ATOMIC); 164 + if (!skb) 165 + return -ENOMEM; 166 + 167 + /* add the genetlink message header */ 168 + msg_header = genlmsg_put(skb, 0, acpi_event_seqnum++, 169 + &acpi_event_genl_family, 0, 170 + ACPI_GENL_CMD_EVENT); 171 + if (!msg_header) { 172 + nlmsg_free(skb); 173 + return -ENOMEM; 174 + } 175 + 176 + /* fill the data */ 177 + attr = 178 + nla_reserve(skb, ACPI_GENL_ATTR_EVENT, 179 + sizeof(struct acpi_genl_event)); 180 + if (!attr) { 181 + nlmsg_free(skb); 182 + return -EINVAL; 183 + } 184 + 185 + event = nla_data(attr); 186 + if (!event) { 187 + nlmsg_free(skb); 188 + return -EINVAL; 189 + } 190 + 191 + memset(event, 0, sizeof(struct acpi_genl_event)); 192 + 193 + strcpy(event->device_class, device->pnp.device_class); 194 + strcpy(event->bus_id, device->dev.bus_id); 195 + event->type = type; 196 + event->data = data; 197 + 198 + /* send multicast genetlink message */ 199 + result = genlmsg_end(skb, msg_header); 200 + if (result < 0) { 201 + nlmsg_free(skb); 202 + return result; 203 + } 204 + 205 + result = 206 + genlmsg_multicast(skb, 0, acpi_event_mcgrp.id, GFP_ATOMIC); 207 + if (result) 208 + ACPI_DEBUG_PRINT((ACPI_DB_INFO, 209 + "Failed to send a Genetlink message!\n")); 210 + return 0; 211 + } 212 + 213 + static int acpi_event_genetlink_init(void) 214 + { 215 + int result; 216 + 217 + result = genl_register_family(&acpi_event_genl_family); 218 + if (result) 219 + return result; 220 + 221 + result = genl_register_mc_group(&acpi_event_genl_family, 222 + &acpi_event_mcgrp); 223 + if (result) 224 + genl_unregister_family(&acpi_event_genl_family); 225 + 226 + return result; 227 + } 228 + 229 + #else 230 + int acpi_bus_generate_genetlink_event(struct acpi_device *device, u8 type, 231 + int data) 232 + { 233 + return 0; 234 + } 235 + 236 + static int acpi_event_genetlink_init(void) 237 + { 238 + return -ENODEV; 239 + } 240 + #endif 241 + 110 242 static int __init acpi_event_init(void) 111 243 { 112 244 struct proc_dir_entry *entry; 113 245 int error = 0; 114 246 115 - 116 247 if (acpi_disabled) 117 248 return 0; 249 + 250 + /* create genetlink for acpi event */ 251 + error = acpi_event_genetlink_init(); 252 + if (error) 253 + printk(KERN_WARNING PREFIX 254 + "Failed to create genetlink family for ACPI event\n"); 118 255 119 256 /* 'event' [R] */ 120 257 entry = create_proc_entry("event", S_IRUSR, acpi_root_dir); 121 258 if (entry) 122 259 entry->proc_fops = &acpi_system_event_ops; 123 - else { 124 - error = -ENODEV; 125 - } 126 - return error; 260 + else 261 + return -ENODEV; 262 + 263 + return 0; 127 264 } 128 265 129 - subsys_initcall(acpi_event_init); 266 + fs_initcall(acpi_event_init);
+4
drivers/acpi/events/evgpeblk.c
··· 586 586 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); 587 587 if (gpe_xrupt->previous) { 588 588 gpe_xrupt->previous->next = gpe_xrupt->next; 589 + } else { 590 + /* No previous, update list head */ 591 + 592 + acpi_gbl_gpe_xrupt_list_head = gpe_xrupt->next; 589 593 } 590 594 591 595 if (gpe_xrupt->next) {
+1
drivers/acpi/events/evrgnini.c
··· 284 284 } 285 285 286 286 if (!pci_device_node) { 287 + ACPI_FREE(pci_id); 287 288 return_ACPI_STATUS(AE_AML_OPERAND_TYPE); 288 289 } 289 290
+1 -1
drivers/acpi/glue.c
··· 16 16 #if ACPI_GLUE_DEBUG 17 17 #define DBG(x...) printk(PREFIX x) 18 18 #else 19 - #define DBG(x...) 19 + #define DBG(x...) do { } while(0) 20 20 #endif 21 21 static LIST_HEAD(bus_type_list); 22 22 static DECLARE_RWSEM(bus_type_sem);
+2 -38
drivers/acpi/osl.c
··· 77 77 #define OSI_STRING_LENGTH_MAX 64 /* arbitrary */ 78 78 static char osi_additional_string[OSI_STRING_LENGTH_MAX]; 79 79 80 - #define OSI_LINUX_ENABLED 81 - #ifdef OSI_LINUX_ENABLED 82 - int osi_linux = 1; /* enable _OSI(Linux) by default */ 83 - #else 84 - int osi_linux; /* disable _OSI(Linux) by default */ 85 - #endif 86 - 80 + static int osi_linux; /* disable _OSI(Linux) by default */ 87 81 88 82 #ifdef CONFIG_DMI 89 83 static struct __initdata dmi_system_id acpi_osl_dmi_table[]; ··· 1177 1183 if (!strcmp("Linux", interface)) { 1178 1184 printk(KERN_WARNING PREFIX 1179 1185 "System BIOS is requesting _OSI(Linux)\n"); 1180 - #ifdef OSI_LINUX_ENABLED 1181 - printk(KERN_WARNING PREFIX 1182 - "Please test with \"acpi_osi=!Linux\"\n" 1183 - "Please send dmidecode " 1184 - "to linux-acpi@vger.kernel.org\n"); 1185 - #else 1186 1186 printk(KERN_WARNING PREFIX 1187 1187 "If \"acpi_osi=Linux\" works better,\n" 1188 1188 "Please send dmidecode " 1189 1189 "to linux-acpi@vger.kernel.org\n"); 1190 - #endif 1191 1190 if(osi_linux) 1192 1191 return AE_OK; 1193 1192 } ··· 1214 1227 } 1215 1228 1216 1229 #ifdef CONFIG_DMI 1217 - #ifdef OSI_LINUX_ENABLED 1218 - static int dmi_osi_not_linux(struct dmi_system_id *d) 1219 - { 1220 - printk(KERN_NOTICE "%s detected: requires not _OSI(Linux)\n", d->ident); 1221 - enable_osi_linux(0); 1222 - return 0; 1223 - } 1224 - #else 1225 1230 static int dmi_osi_linux(struct dmi_system_id *d) 1226 1231 { 1227 - printk(KERN_NOTICE "%s detected: requires _OSI(Linux)\n", d->ident); 1232 + printk(KERN_NOTICE "%s detected: enabling _OSI(Linux)\n", d->ident); 1228 1233 enable_osi_linux(1); 1229 1234 return 0; 1230 1235 } 1231 - #endif 1232 1236 1233 1237 static struct dmi_system_id acpi_osl_dmi_table[] __initdata = { 1234 - #ifdef OSI_LINUX_ENABLED 1235 - /* 1236 - * Boxes that need NOT _OSI(Linux) 1237 - */ 1238 - { 1239 - .callback = dmi_osi_not_linux, 1240 - .ident = "Toshiba Satellite P100", 1241 - .matches = { 1242 - DMI_MATCH(DMI_BOARD_VENDOR, "TOSHIBA"), 1243 - DMI_MATCH(DMI_BOARD_NAME, "Satellite P100"), 1244 - }, 1245 - }, 1246 - #else 1247 1238 /* 1248 1239 * Boxes that need _OSI(Linux) 1249 1240 */ ··· 1233 1268 DMI_MATCH(DMI_BOARD_NAME, "MPAD-MSAE Customer Reference Boards"), 1234 1269 }, 1235 1270 }, 1236 - #endif 1237 1271 {} 1238 1272 }; 1239 1273 #endif /* CONFIG_DMI */
+1 -1
drivers/acpi/pci_link.c
··· 733 733 /* query and set link->irq.active */ 734 734 acpi_pci_link_get_current(link); 735 735 736 - printk(PREFIX "%s [%s] (IRQs", acpi_device_name(device), 736 + printk(KERN_INFO PREFIX "%s [%s] (IRQs", acpi_device_name(device), 737 737 acpi_device_bid(device)); 738 738 for (i = 0; i < link->irq.possible_count; i++) { 739 739 if (link->irq.active == link->irq.possible[i]) {
+6
drivers/acpi/processor_core.c
··· 66 66 #define ACPI_PROCESSOR_FILE_LIMIT "limit" 67 67 #define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80 68 68 #define ACPI_PROCESSOR_NOTIFY_POWER 0x81 69 + #define ACPI_PROCESSOR_NOTIFY_THROTTLING 0x82 69 70 70 71 #define ACPI_PROCESSOR_LIMIT_USER 0 71 72 #define ACPI_PROCESSOR_LIMIT_THERMAL 1 ··· 85 84 static void acpi_processor_notify(acpi_handle handle, u32 event, void *data); 86 85 static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu); 87 86 static int acpi_processor_handle_eject(struct acpi_processor *pr); 87 + extern int acpi_processor_tstate_has_changed(struct acpi_processor *pr); 88 + 88 89 89 90 static struct acpi_driver acpi_processor_driver = { 90 91 .name = "processor", ··· 699 696 acpi_processor_cst_has_changed(pr); 700 697 acpi_bus_generate_event(device, event, 0); 701 698 break; 699 + case ACPI_PROCESSOR_NOTIFY_THROTTLING: 700 + acpi_processor_tstate_has_changed(pr); 701 + acpi_bus_generate_event(device, event, 0); 702 702 default: 703 703 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 704 704 "Unsupported event [0x%x]\n", event));
+15 -5
drivers/acpi/processor_idle.c
··· 490 490 491 491 case ACPI_STATE_C3: 492 492 493 - if (pr->flags.bm_check) { 493 + /* 494 + * disable bus master 495 + * bm_check implies we need ARB_DIS 496 + * !bm_check implies we need cache flush 497 + * bm_control implies whether we can do ARB_DIS 498 + * 499 + * That leaves a case where bm_check is set and bm_control is 500 + * not set. In that case we cannot do much, we enter C3 501 + * without doing anything. 502 + */ 503 + if (pr->flags.bm_check && pr->flags.bm_control) { 494 504 if (atomic_inc_return(&c3_cpu_count) == 495 505 num_online_cpus()) { 496 506 /* ··· 509 499 */ 510 500 acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1); 511 501 } 512 - } else { 502 + } else if (!pr->flags.bm_check) { 513 503 /* SMP with no shared cache... Invalidate cache */ 514 504 ACPI_FLUSH_CPU_CACHE(); 515 505 } ··· 521 511 acpi_cstate_enter(cx); 522 512 /* Get end time (ticks) */ 523 513 t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); 524 - if (pr->flags.bm_check) { 514 + if (pr->flags.bm_check && pr->flags.bm_control) { 525 515 /* Enable bus master arbitration */ 526 516 atomic_dec(&c3_cpu_count); 527 517 acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0); ··· 971 961 if (pr->flags.bm_check) { 972 962 /* bus mastering control is necessary */ 973 963 if (!pr->flags.bm_control) { 964 + /* In this case we enter C3 without bus mastering */ 974 965 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 975 - "C3 support requires bus mastering control\n")); 976 - return; 966 + "C3 support without bus mastering control\n")); 977 967 } 978 968 } else { 979 969 /*
+395 -15
drivers/acpi/processor_throttling.c
··· 44 44 #define _COMPONENT ACPI_PROCESSOR_COMPONENT 45 45 ACPI_MODULE_NAME("processor_throttling"); 46 46 47 + static int acpi_processor_get_throttling(struct acpi_processor *pr); 48 + int acpi_processor_set_throttling(struct acpi_processor *pr, int state); 49 + 50 + static int acpi_processor_get_platform_limit(struct acpi_processor *pr) 51 + { 52 + acpi_status status = 0; 53 + unsigned long tpc = 0; 54 + 55 + if (!pr) 56 + return -EINVAL; 57 + status = acpi_evaluate_integer(pr->handle, "_TPC", NULL, &tpc); 58 + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 59 + ACPI_EXCEPTION((AE_INFO, status, "Evaluating _TPC")); 60 + return -ENODEV; 61 + } 62 + pr->throttling_platform_limit = (int)tpc; 63 + return 0; 64 + } 65 + 66 + int acpi_processor_tstate_has_changed(struct acpi_processor *pr) 67 + { 68 + return acpi_processor_get_platform_limit(pr); 69 + } 70 + 71 + /* -------------------------------------------------------------------------- 72 + _PTC, _TSS, _TSD support 73 + -------------------------------------------------------------------------- */ 74 + static int acpi_processor_get_throttling_control(struct acpi_processor *pr) 75 + { 76 + int result = 0; 77 + acpi_status status = 0; 78 + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 79 + union acpi_object *ptc = NULL; 80 + union acpi_object obj = { 0 }; 81 + 82 + status = acpi_evaluate_object(pr->handle, "_PTC", NULL, &buffer); 83 + if (ACPI_FAILURE(status)) { 84 + ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PTC")); 85 + return -ENODEV; 86 + } 87 + 88 + ptc = (union acpi_object *)buffer.pointer; 89 + if (!ptc || (ptc->type != ACPI_TYPE_PACKAGE) 90 + || (ptc->package.count != 2)) { 91 + printk(KERN_ERR PREFIX "Invalid _PTC data\n"); 92 + result = -EFAULT; 93 + goto end; 94 + } 95 + 96 + /* 97 + * control_register 98 + */ 99 + 100 + obj = ptc->package.elements[0]; 101 + 102 + if ((obj.type != ACPI_TYPE_BUFFER) 103 + || (obj.buffer.length < sizeof(struct acpi_ptc_register)) 104 + || (obj.buffer.pointer == NULL)) { 105 + printk(KERN_ERR PREFIX 106 + "Invalid _PTC data (control_register)\n"); 107 + result = -EFAULT; 108 + goto end; 109 + } 110 + memcpy(&pr->throttling.control_register, obj.buffer.pointer, 111 + sizeof(struct acpi_ptc_register)); 112 + 113 + /* 114 + * status_register 115 + */ 116 + 117 + obj = ptc->package.elements[1]; 118 + 119 + if ((obj.type != ACPI_TYPE_BUFFER) 120 + || (obj.buffer.length < sizeof(struct acpi_ptc_register)) 121 + || (obj.buffer.pointer == NULL)) { 122 + printk(KERN_ERR PREFIX "Invalid _PTC data (status_register)\n"); 123 + result = -EFAULT; 124 + goto end; 125 + } 126 + 127 + memcpy(&pr->throttling.status_register, obj.buffer.pointer, 128 + sizeof(struct acpi_ptc_register)); 129 + 130 + end: 131 + kfree(buffer.pointer); 132 + 133 + return result; 134 + } 135 + static int acpi_processor_get_throttling_states(struct acpi_processor *pr) 136 + { 137 + int result = 0; 138 + acpi_status status = AE_OK; 139 + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 140 + struct acpi_buffer format = { sizeof("NNNNN"), "NNNNN" }; 141 + struct acpi_buffer state = { 0, NULL }; 142 + union acpi_object *tss = NULL; 143 + int i; 144 + 145 + status = acpi_evaluate_object(pr->handle, "_TSS", NULL, &buffer); 146 + if (ACPI_FAILURE(status)) { 147 + ACPI_EXCEPTION((AE_INFO, status, "Evaluating _TSS")); 148 + return -ENODEV; 149 + } 150 + 151 + tss = buffer.pointer; 152 + if (!tss || (tss->type != ACPI_TYPE_PACKAGE)) { 153 + printk(KERN_ERR PREFIX "Invalid _TSS data\n"); 154 + result = -EFAULT; 155 + goto end; 156 + } 157 + 158 + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d throttling states\n", 159 + tss->package.count)); 160 + 161 + pr->throttling.state_count = tss->package.count; 162 + pr->throttling.states_tss = 163 + kmalloc(sizeof(struct acpi_processor_tx_tss) * tss->package.count, 164 + GFP_KERNEL); 165 + if (!pr->throttling.states_tss) { 166 + result = -ENOMEM; 167 + goto end; 168 + } 169 + 170 + for (i = 0; i < pr->throttling.state_count; i++) { 171 + 172 + struct acpi_processor_tx_tss *tx = 173 + (struct acpi_processor_tx_tss *)&(pr->throttling. 174 + states_tss[i]); 175 + 176 + state.length = sizeof(struct acpi_processor_tx_tss); 177 + state.pointer = tx; 178 + 179 + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Extracting state %d\n", i)); 180 + 181 + status = acpi_extract_package(&(tss->package.elements[i]), 182 + &format, &state); 183 + if (ACPI_FAILURE(status)) { 184 + ACPI_EXCEPTION((AE_INFO, status, "Invalid _TSS data")); 185 + result = -EFAULT; 186 + kfree(pr->throttling.states_tss); 187 + goto end; 188 + } 189 + 190 + if (!tx->freqpercentage) { 191 + printk(KERN_ERR PREFIX 192 + "Invalid _TSS data: freq is zero\n"); 193 + result = -EFAULT; 194 + kfree(pr->throttling.states_tss); 195 + goto end; 196 + } 197 + } 198 + 199 + end: 200 + kfree(buffer.pointer); 201 + 202 + return result; 203 + } 204 + static int acpi_processor_get_tsd(struct acpi_processor *pr) 205 + { 206 + int result = 0; 207 + acpi_status status = AE_OK; 208 + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 209 + struct acpi_buffer format = { sizeof("NNNNN"), "NNNNN" }; 210 + struct acpi_buffer state = { 0, NULL }; 211 + union acpi_object *tsd = NULL; 212 + struct acpi_tsd_package *pdomain; 213 + 214 + status = acpi_evaluate_object(pr->handle, "_TSD", NULL, &buffer); 215 + if (ACPI_FAILURE(status)) { 216 + return -ENODEV; 217 + } 218 + 219 + tsd = buffer.pointer; 220 + if (!tsd || (tsd->type != ACPI_TYPE_PACKAGE)) { 221 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n")); 222 + result = -EFAULT; 223 + goto end; 224 + } 225 + 226 + if (tsd->package.count != 1) { 227 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n")); 228 + result = -EFAULT; 229 + goto end; 230 + } 231 + 232 + pdomain = &(pr->throttling.domain_info); 233 + 234 + state.length = sizeof(struct acpi_tsd_package); 235 + state.pointer = pdomain; 236 + 237 + status = acpi_extract_package(&(tsd->package.elements[0]), 238 + &format, &state); 239 + if (ACPI_FAILURE(status)) { 240 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _TSD data\n")); 241 + result = -EFAULT; 242 + goto end; 243 + } 244 + 245 + if (pdomain->num_entries != ACPI_TSD_REV0_ENTRIES) { 246 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _TSD:num_entries\n")); 247 + result = -EFAULT; 248 + goto end; 249 + } 250 + 251 + if (pdomain->revision != ACPI_TSD_REV0_REVISION) { 252 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Unknown _TSD:revision\n")); 253 + result = -EFAULT; 254 + goto end; 255 + } 256 + 257 + end: 258 + kfree(buffer.pointer); 259 + return result; 260 + } 261 + 47 262 /* -------------------------------------------------------------------------- 48 263 Throttling Control 49 264 -------------------------------------------------------------------------- */ 50 - static int acpi_processor_get_throttling(struct acpi_processor *pr) 265 + static int acpi_processor_get_throttling_fadt(struct acpi_processor *pr) 51 266 { 52 267 int state = 0; 53 268 u32 value = 0; 54 269 u32 duty_mask = 0; 55 270 u32 duty_value = 0; 56 - 57 271 58 272 if (!pr) 59 273 return -EINVAL; ··· 308 94 return 0; 309 95 } 310 96 311 - int acpi_processor_set_throttling(struct acpi_processor *pr, int state) 97 + static int acpi_read_throttling_status(struct acpi_processor_throttling 98 + *throttling) 99 + { 100 + int value = -1; 101 + switch (throttling->status_register.space_id) { 102 + case ACPI_ADR_SPACE_SYSTEM_IO: 103 + acpi_os_read_port((acpi_io_address) throttling->status_register. 104 + address, &value, 105 + (u32) throttling->status_register.bit_width * 106 + 8); 107 + break; 108 + case ACPI_ADR_SPACE_FIXED_HARDWARE: 109 + printk(KERN_ERR PREFIX 110 + "HARDWARE addr space,NOT supported yet\n"); 111 + break; 112 + default: 113 + printk(KERN_ERR PREFIX "Unknown addr space %d\n", 114 + (u32) (throttling->status_register.space_id)); 115 + } 116 + return value; 117 + } 118 + 119 + static int acpi_write_throttling_state(struct acpi_processor_throttling 120 + *throttling, int value) 121 + { 122 + int ret = -1; 123 + 124 + switch (throttling->control_register.space_id) { 125 + case ACPI_ADR_SPACE_SYSTEM_IO: 126 + acpi_os_write_port((acpi_io_address) throttling-> 127 + control_register.address, value, 128 + (u32) throttling->control_register. 129 + bit_width * 8); 130 + ret = 0; 131 + break; 132 + case ACPI_ADR_SPACE_FIXED_HARDWARE: 133 + printk(KERN_ERR PREFIX 134 + "HARDWARE addr space,NOT supported yet\n"); 135 + break; 136 + default: 137 + printk(KERN_ERR PREFIX "Unknown addr space %d\n", 138 + (u32) (throttling->control_register.space_id)); 139 + } 140 + return ret; 141 + } 142 + 143 + static int acpi_get_throttling_state(struct acpi_processor *pr, int value) 144 + { 145 + int i; 146 + 147 + for (i = 0; i < pr->throttling.state_count; i++) { 148 + struct acpi_processor_tx_tss *tx = 149 + (struct acpi_processor_tx_tss *)&(pr->throttling. 150 + states_tss[i]); 151 + if (tx->control == value) 152 + break; 153 + } 154 + if (i > pr->throttling.state_count) 155 + i = -1; 156 + return i; 157 + } 158 + 159 + static int acpi_get_throttling_value(struct acpi_processor *pr, int state) 160 + { 161 + int value = -1; 162 + if (state >= 0 && state <= pr->throttling.state_count) { 163 + struct acpi_processor_tx_tss *tx = 164 + (struct acpi_processor_tx_tss *)&(pr->throttling. 165 + states_tss[state]); 166 + value = tx->control; 167 + } 168 + return value; 169 + } 170 + 171 + static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr) 172 + { 173 + int state = 0; 174 + u32 value = 0; 175 + 176 + if (!pr) 177 + return -EINVAL; 178 + 179 + if (!pr->flags.throttling) 180 + return -ENODEV; 181 + 182 + pr->throttling.state = 0; 183 + local_irq_disable(); 184 + value = acpi_read_throttling_status(&pr->throttling); 185 + if (value >= 0) { 186 + state = acpi_get_throttling_state(pr, value); 187 + pr->throttling.state = state; 188 + } 189 + local_irq_enable(); 190 + 191 + return 0; 192 + } 193 + 194 + static int acpi_processor_get_throttling(struct acpi_processor *pr) 195 + { 196 + return pr->throttling.acpi_processor_get_throttling(pr); 197 + } 198 + 199 + static int acpi_processor_set_throttling_fadt(struct acpi_processor *pr, 200 + int state) 312 201 { 313 202 u32 value = 0; 314 203 u32 duty_mask = 0; 315 204 u32 duty_value = 0; 316 - 317 205 318 206 if (!pr) 319 207 return -EINVAL; ··· 429 113 if (state == pr->throttling.state) 430 114 return 0; 431 115 116 + if (state < pr->throttling_platform_limit) 117 + return -EPERM; 432 118 /* 433 119 * Calculate the duty_value and duty_mask. 434 120 */ ··· 483 165 return 0; 484 166 } 485 167 168 + static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr, 169 + int state) 170 + { 171 + u32 value = 0; 172 + 173 + if (!pr) 174 + return -EINVAL; 175 + 176 + if ((state < 0) || (state > (pr->throttling.state_count - 1))) 177 + return -EINVAL; 178 + 179 + if (!pr->flags.throttling) 180 + return -ENODEV; 181 + 182 + if (state == pr->throttling.state) 183 + return 0; 184 + 185 + if (state < pr->throttling_platform_limit) 186 + return -EPERM; 187 + 188 + local_irq_disable(); 189 + 190 + value = acpi_get_throttling_value(pr, state); 191 + if (value >= 0) { 192 + acpi_write_throttling_state(&pr->throttling, value); 193 + pr->throttling.state = state; 194 + } 195 + local_irq_enable(); 196 + 197 + return 0; 198 + } 199 + 200 + int acpi_processor_set_throttling(struct acpi_processor *pr, int state) 201 + { 202 + return pr->throttling.acpi_processor_set_throttling(pr, state); 203 + } 204 + 486 205 int acpi_processor_get_throttling_info(struct acpi_processor *pr) 487 206 { 488 207 int result = 0; 489 208 int step = 0; 490 209 int i = 0; 491 - 210 + int no_ptc = 0; 211 + int no_tss = 0; 212 + int no_tsd = 0; 492 213 493 214 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 494 215 "pblk_address[0x%08x] duty_offset[%d] duty_width[%d]\n", ··· 539 182 return -EINVAL; 540 183 541 184 /* TBD: Support ACPI 2.0 objects */ 185 + no_ptc = acpi_processor_get_throttling_control(pr); 186 + no_tss = acpi_processor_get_throttling_states(pr); 187 + no_tsd = acpi_processor_get_tsd(pr); 188 + 189 + if (no_ptc || no_tss) { 190 + pr->throttling.acpi_processor_get_throttling = 191 + &acpi_processor_get_throttling_fadt; 192 + pr->throttling.acpi_processor_set_throttling = 193 + &acpi_processor_set_throttling_fadt; 194 + } else { 195 + pr->throttling.acpi_processor_get_throttling = 196 + &acpi_processor_get_throttling_ptc; 197 + pr->throttling.acpi_processor_set_throttling = 198 + &acpi_processor_set_throttling_ptc; 199 + } 542 200 543 201 if (!pr->throttling.address) { 544 202 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling register\n")); ··· 634 262 int i = 0; 635 263 int result = 0; 636 264 637 - 638 265 if (!pr) 639 266 goto end; 640 267 ··· 651 280 } 652 281 653 282 seq_printf(seq, "state count: %d\n" 654 - "active state: T%d\n", 655 - pr->throttling.state_count, pr->throttling.state); 283 + "active state: T%d\n" 284 + "state available: T%d to T%d\n", 285 + pr->throttling.state_count, pr->throttling.state, 286 + pr->throttling_platform_limit, 287 + pr->throttling.state_count - 1); 656 288 657 289 seq_puts(seq, "states:\n"); 658 - for (i = 0; i < pr->throttling.state_count; i++) 659 - seq_printf(seq, " %cT%d: %02d%%\n", 660 - (i == pr->throttling.state ? '*' : ' '), i, 661 - (pr->throttling.states[i].performance ? pr-> 662 - throttling.states[i].performance / 10 : 0)); 290 + if (acpi_processor_get_throttling == acpi_processor_get_throttling_fadt) 291 + for (i = 0; i < pr->throttling.state_count; i++) 292 + seq_printf(seq, " %cT%d: %02d%%\n", 293 + (i == pr->throttling.state ? '*' : ' '), i, 294 + (pr->throttling.states[i].performance ? pr-> 295 + throttling.states[i].performance / 10 : 0)); 296 + else 297 + for (i = 0; i < pr->throttling.state_count; i++) 298 + seq_printf(seq, " %cT%d: %02d%%\n", 299 + (i == pr->throttling.state ? '*' : ' '), i, 300 + (int)pr->throttling.states_tss[i]. 301 + freqpercentage); 663 302 664 303 end: 665 304 return 0; ··· 682 301 PDE(inode)->data); 683 302 } 684 303 685 - static ssize_t acpi_processor_write_throttling(struct file * file, 304 + static ssize_t acpi_processor_write_throttling(struct file *file, 686 305 const char __user * buffer, 687 306 size_t count, loff_t * data) 688 307 { ··· 690 309 struct seq_file *m = file->private_data; 691 310 struct acpi_processor *pr = m->private; 692 311 char state_string[12] = { '\0' }; 693 - 694 312 695 313 if (!pr || (count > sizeof(state_string) - 1)) 696 314 return -EINVAL;
+7 -26
drivers/acpi/sbs.c
··· 127 127 static struct acpi_driver acpi_sbs_driver = { 128 128 .name = "sbs", 129 129 .class = ACPI_SBS_CLASS, 130 - .ids = ACPI_SBS_HID, 130 + .ids = "ACPI0001,ACPI0005", 131 131 .ops = { 132 132 .add = acpi_sbs_add, 133 133 .remove = acpi_sbs_remove, ··· 176 176 }; 177 177 178 178 struct acpi_sbs { 179 - acpi_handle handle; 180 179 int base; 181 180 struct acpi_device *device; 182 - struct acpi_ec_smbus *smbus; 183 181 struct mutex mutex; 184 182 int sbsm_present; 185 183 int sbsm_batteries_supported; ··· 509 511 "acpi_sbs_read_word() failed")); 510 512 goto end; 511 513 } 512 - 514 + sbs->sbsm_present = 1; 513 515 sbs->sbsm_batteries_supported = battery_system_info & 0x000f; 514 516 515 517 end: ··· 1628 1630 { 1629 1631 struct acpi_sbs *sbs = NULL; 1630 1632 int result = 0, remove_result = 0; 1631 - unsigned long sbs_obj; 1632 1633 int id; 1633 1634 acpi_status status = AE_OK; 1634 1635 unsigned long val; 1635 1636 1636 1637 status = 1637 - acpi_evaluate_integer(device->parent->handle, "_EC", NULL, &val); 1638 + acpi_evaluate_integer(device->handle, "_EC", NULL, &val); 1638 1639 if (ACPI_FAILURE(status)) { 1639 1640 ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Error obtaining _EC")); 1640 1641 return -EIO; ··· 1650 1653 1651 1654 sbs_mutex_lock(sbs); 1652 1655 1653 - sbs->base = (val & 0xff00ull) >> 8; 1656 + sbs->base = 0xff & (val >> 8); 1654 1657 sbs->device = device; 1655 1658 1656 1659 strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME); ··· 1662 1665 ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_ac_add() failed")); 1663 1666 goto end; 1664 1667 } 1665 - status = acpi_evaluate_integer(device->handle, "_SBS", NULL, &sbs_obj); 1666 - if (status) { 1667 - ACPI_EXCEPTION((AE_INFO, status, 1668 - "acpi_evaluate_integer() failed")); 1669 - result = -EIO; 1670 - goto end; 1671 - } 1672 - if (sbs_obj > 0) { 1673 - result = acpi_sbsm_get_info(sbs); 1674 - if (result) { 1675 - ACPI_EXCEPTION((AE_INFO, AE_ERROR, 1676 - "acpi_sbsm_get_info() failed")); 1677 - goto end; 1678 - } 1679 - sbs->sbsm_present = 1; 1680 - } 1681 1668 1682 - if (sbs->sbsm_present == 0) { 1669 + acpi_sbsm_get_info(sbs); 1670 + 1671 + if (!sbs->sbsm_present) { 1683 1672 result = acpi_battery_add(sbs, 0); 1684 1673 if (result) { 1685 1674 ACPI_EXCEPTION((AE_INFO, AE_ERROR, ··· 1684 1701 } 1685 1702 } 1686 1703 } 1687 - 1688 - sbs->handle = device->handle; 1689 1704 1690 1705 init_timer(&sbs->update_timer); 1691 1706 result = acpi_check_update_proc(sbs);
-5
drivers/acpi/sleep/main.c
··· 210 210 211 211 /* reset firmware waking vector */ 212 212 acpi_set_firmware_waking_vector((acpi_physical_address) 0); 213 - 214 - if (init_8259A_after_S1) { 215 - printk("Broken toshiba laptop -> kicking interrupts\n"); 216 - init_8259A(0); 217 - } 218 213 } 219 214 220 215 static int acpi_hibernation_pre_restore(void)
+144 -21
drivers/acpi/system.c
··· 39 39 40 40 #define ACPI_SYSTEM_CLASS "system" 41 41 #define ACPI_SYSTEM_DEVICE_NAME "System" 42 - #define ACPI_SYSTEM_FILE_INFO "info" 43 - #define ACPI_SYSTEM_FILE_EVENT "event" 44 - #define ACPI_SYSTEM_FILE_DSDT "dsdt" 45 - #define ACPI_SYSTEM_FILE_FADT "fadt" 46 42 47 43 /* 48 44 * Make ACPICA version work as module param 49 45 */ 50 - static int param_get_acpica_version(char *buffer, struct kernel_param *kp) { 46 + static int param_get_acpica_version(char *buffer, struct kernel_param *kp) 47 + { 51 48 int result; 52 49 53 50 result = sprintf(buffer, "%x", ACPI_CA_VERSION); ··· 55 58 module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444); 56 59 57 60 /* -------------------------------------------------------------------------- 61 + FS Interface (/sys) 62 + -------------------------------------------------------------------------- */ 63 + static LIST_HEAD(acpi_table_attr_list); 64 + static struct kobject tables_kobj; 65 + 66 + struct acpi_table_attr { 67 + struct bin_attribute attr; 68 + char name[8]; 69 + int instance; 70 + struct list_head node; 71 + }; 72 + 73 + static ssize_t acpi_table_show(struct kobject *kobj, 74 + struct bin_attribute *bin_attr, char *buf, 75 + loff_t offset, size_t count) 76 + { 77 + struct acpi_table_attr *table_attr = 78 + container_of(bin_attr, struct acpi_table_attr, attr); 79 + struct acpi_table_header *table_header = NULL; 80 + acpi_status status; 81 + ssize_t ret_count = count; 82 + 83 + status = 84 + acpi_get_table(table_attr->name, table_attr->instance, 85 + &table_header); 86 + if (ACPI_FAILURE(status)) 87 + return -ENODEV; 88 + 89 + if (offset >= table_header->length) { 90 + ret_count = 0; 91 + goto end; 92 + } 93 + 94 + if (offset + ret_count > table_header->length) 95 + ret_count = table_header->length - offset; 96 + 97 + memcpy(buf, ((char *)table_header) + offset, ret_count); 98 + 99 + end: 100 + return ret_count; 101 + } 102 + 103 + static void acpi_table_attr_init(struct acpi_table_attr *table_attr, 104 + struct acpi_table_header *table_header) 105 + { 106 + struct acpi_table_header *header = NULL; 107 + struct acpi_table_attr *attr = NULL; 108 + 109 + memcpy(table_attr->name, table_header->signature, ACPI_NAME_SIZE); 110 + 111 + list_for_each_entry(attr, &acpi_table_attr_list, node) { 112 + if (!memcmp(table_header->signature, attr->name, 113 + ACPI_NAME_SIZE)) 114 + if (table_attr->instance < attr->instance) 115 + table_attr->instance = attr->instance; 116 + } 117 + table_attr->instance++; 118 + 119 + if (table_attr->instance > 1 || (table_attr->instance == 1 && 120 + !acpi_get_table(table_header-> 121 + signature, 2, 122 + &header))) 123 + sprintf(table_attr->name + 4, "%d", table_attr->instance); 124 + 125 + table_attr->attr.size = 0; 126 + table_attr->attr.read = acpi_table_show; 127 + table_attr->attr.attr.name = table_attr->name; 128 + table_attr->attr.attr.mode = 0444; 129 + table_attr->attr.attr.owner = THIS_MODULE; 130 + 131 + return; 132 + } 133 + 134 + static int acpi_system_sysfs_init(void) 135 + { 136 + struct acpi_table_attr *table_attr; 137 + struct acpi_table_header *table_header = NULL; 138 + int table_index = 0; 139 + int result; 140 + 141 + tables_kobj.parent = &acpi_subsys.kobj; 142 + kobject_set_name(&tables_kobj, "tables"); 143 + result = kobject_register(&tables_kobj); 144 + if (result) 145 + return result; 146 + 147 + do { 148 + result = acpi_get_table_by_index(table_index, &table_header); 149 + if (!result) { 150 + table_index++; 151 + table_attr = NULL; 152 + table_attr = 153 + kzalloc(sizeof(struct acpi_table_attr), GFP_KERNEL); 154 + if (!table_attr) 155 + return -ENOMEM; 156 + 157 + acpi_table_attr_init(table_attr, table_header); 158 + result = 159 + sysfs_create_bin_file(&tables_kobj, 160 + &table_attr->attr); 161 + if (result) { 162 + kfree(table_attr); 163 + return result; 164 + } else 165 + list_add_tail(&table_attr->node, 166 + &acpi_table_attr_list); 167 + } 168 + } while (!result); 169 + 170 + return 0; 171 + } 172 + 173 + /* -------------------------------------------------------------------------- 58 174 FS Interface (/proc) 59 175 -------------------------------------------------------------------------- */ 60 176 #ifdef CONFIG_ACPI_PROCFS 177 + #define ACPI_SYSTEM_FILE_INFO "info" 178 + #define ACPI_SYSTEM_FILE_EVENT "event" 179 + #define ACPI_SYSTEM_FILE_DSDT "dsdt" 180 + #define ACPI_SYSTEM_FILE_FADT "fadt" 61 181 62 182 static int acpi_system_read_info(struct seq_file *seq, void *offset) 63 183 { ··· 194 80 .llseek = seq_lseek, 195 81 .release = single_release, 196 82 }; 197 - #endif 198 83 199 84 static ssize_t acpi_system_read_dsdt(struct file *, char __user *, size_t, 200 85 loff_t *); ··· 210 97 struct acpi_table_header *dsdt = NULL; 211 98 ssize_t res; 212 99 213 - 214 100 status = acpi_get_table(ACPI_SIG_DSDT, 1, &dsdt); 215 101 if (ACPI_FAILURE(status)) 216 102 return -ENODEV; 217 103 218 - res = simple_read_from_buffer(buffer, count, ppos, 219 - dsdt, dsdt->length); 104 + res = simple_read_from_buffer(buffer, count, ppos, dsdt, dsdt->length); 220 105 221 106 return res; 222 107 } ··· 234 123 struct acpi_table_header *fadt = NULL; 235 124 ssize_t res; 236 125 237 - 238 126 status = acpi_get_table(ACPI_SIG_FADT, 1, &fadt); 239 127 if (ACPI_FAILURE(status)) 240 128 return -ENODEV; 241 129 242 - res = simple_read_from_buffer(buffer, count, ppos, 243 - fadt, fadt->length); 130 + res = simple_read_from_buffer(buffer, count, ppos, fadt, fadt->length); 244 131 245 132 return res; 246 133 } 247 134 248 - static int __init acpi_system_init(void) 135 + static int acpi_system_procfs_init(void) 249 136 { 250 137 struct proc_dir_entry *entry; 251 138 int error = 0; 252 139 char *name; 253 140 254 - 255 - if (acpi_disabled) 256 - return 0; 257 - 258 - #ifdef CONFIG_ACPI_PROCFS 259 141 /* 'info' [R] */ 260 142 name = ACPI_SYSTEM_FILE_INFO; 261 143 entry = create_proc_entry(name, S_IRUGO, acpi_root_dir); ··· 257 153 else { 258 154 entry->proc_fops = &acpi_system_info_ops; 259 155 } 260 - #endif 261 156 262 157 /* 'dsdt' [R] */ 263 158 name = ACPI_SYSTEM_FILE_DSDT; ··· 280 177 Error: 281 178 remove_proc_entry(ACPI_SYSTEM_FILE_FADT, acpi_root_dir); 282 179 remove_proc_entry(ACPI_SYSTEM_FILE_DSDT, acpi_root_dir); 283 - #ifdef CONFIG_ACPI_PROCFS 284 180 remove_proc_entry(ACPI_SYSTEM_FILE_INFO, acpi_root_dir); 285 - #endif 286 181 287 182 error = -EFAULT; 288 183 goto Done; 184 + } 185 + #else 186 + static int acpi_system_procfs_init(void) 187 + { 188 + return 0; 189 + } 190 + #endif 191 + 192 + static int __init acpi_system_init(void) 193 + { 194 + int result = 0; 195 + 196 + if (acpi_disabled) 197 + return 0; 198 + 199 + result = acpi_system_procfs_init(); 200 + if (result) 201 + return result; 202 + 203 + result = acpi_system_sysfs_init(); 204 + 205 + return result; 289 206 } 290 207 291 208 subsys_initcall(acpi_system_init);
+26 -18
drivers/acpi/tables/tbfadt.c
··· 211 211 * DESCRIPTION: Get a local copy of the FADT and convert it to a common format. 212 212 * Performs validation on some important FADT fields. 213 213 * 214 + * NOTE: We create a local copy of the FADT regardless of the version. 215 + * 214 216 ******************************************************************************/ 215 217 216 218 void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) 217 219 { 218 220 219 221 /* 220 - * Check if the FADT is larger than what we know about (ACPI 2.0 version). 221 - * Truncate the table, but make some noise. 222 + * Check if the FADT is larger than the largest table that we expect 223 + * (the ACPI 2.0/3.0 version). If so, truncate the table, and issue 224 + * a warning. 222 225 */ 223 226 if (length > sizeof(struct acpi_table_fadt)) { 224 227 ACPI_WARNING((AE_INFO, ··· 230 227 sizeof(struct acpi_table_fadt))); 231 228 } 232 229 233 - /* Copy the entire FADT locally. Zero first for tb_convert_fadt */ 230 + /* Clear the entire local FADT */ 234 231 235 232 ACPI_MEMSET(&acpi_gbl_FADT, 0, sizeof(struct acpi_table_fadt)); 233 + 234 + /* Copy the original FADT, up to sizeof (struct acpi_table_fadt) */ 236 235 237 236 ACPI_MEMCPY(&acpi_gbl_FADT, table, 238 237 ACPI_MIN(length, sizeof(struct acpi_table_fadt))); ··· 256 251 * RETURN: None 257 252 * 258 253 * DESCRIPTION: Converts all versions of the FADT to a common internal format. 259 - * -> Expand all 32-bit addresses to 64-bit. 254 + * Expand all 32-bit addresses to 64-bit. 260 255 * 261 256 * NOTE: acpi_gbl_FADT must be of size (struct acpi_table_fadt), 262 257 * and must contain a copy of the actual FADT. ··· 297 292 } 298 293 299 294 /* 300 - * Expand the 32-bit V1.0 addresses to the 64-bit "X" generic address 301 - * structures as necessary. 295 + * For ACPI 1.0 FADTs (revision 1 or 2), ensure that reserved fields which 296 + * should be zero are indeed zero. This will workaround BIOSs that 297 + * inadvertently place values in these fields. 298 + * 299 + * The ACPI 1.0 reserved fields that will be zeroed are the bytes located at 300 + * offset 45, 55, 95, and the word located at offset 109, 110. 301 + */ 302 + if (acpi_gbl_FADT.header.revision < 3) { 303 + acpi_gbl_FADT.preferred_profile = 0; 304 + acpi_gbl_FADT.pstate_control = 0; 305 + acpi_gbl_FADT.cst_control = 0; 306 + acpi_gbl_FADT.boot_flags = 0; 307 + } 308 + 309 + /* 310 + * Expand the ACPI 1.0 32-bit V1.0 addresses to the ACPI 2.0 64-bit "X" 311 + * generic address structures as necessary. 302 312 */ 303 313 for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { 304 314 target = ··· 368 348 acpi_gbl_xpm1b_enable.space_id = 369 349 acpi_gbl_FADT.xpm1a_event_block.space_id; 370 350 371 - } 372 - 373 - /* 374 - * For ACPI 1.0 FADTs, ensure that reserved fields (which should be zero) 375 - * are indeed zero. This will workaround BIOSs that inadvertently placed 376 - * values in these fields. 377 - */ 378 - if (acpi_gbl_FADT.header.revision < 3) { 379 - acpi_gbl_FADT.preferred_profile = 0; 380 - acpi_gbl_FADT.pstate_control = 0; 381 - acpi_gbl_FADT.cst_control = 0; 382 - acpi_gbl_FADT.boot_flags = 0; 383 351 } 384 352 } 385 353
+7 -10
drivers/acpi/utilities/uteval.c
··· 62 62 static char *acpi_interfaces_supported[] = { 63 63 /* Operating System Vendor Strings */ 64 64 65 - "Windows 2000", 66 - "Windows 2001", 67 - "Windows 2001 SP0", 68 - "Windows 2001 SP1", 69 - "Windows 2001 SP2", 70 - "Windows 2001 SP3", 71 - "Windows 2001 SP4", 72 - "Windows 2001.1", 73 - "Windows 2001.1 SP1", /* Added 03/2006 */ 74 - "Windows 2006", /* Added 03/2006 */ 65 + "Windows 2000", /* Windows 2000 */ 66 + "Windows 2001", /* Windows XP */ 67 + "Windows 2001 SP1", /* Windows XP SP1 */ 68 + "Windows 2001 SP2", /* Windows XP SP2 */ 69 + "Windows 2001.1", /* Windows Server 2003 */ 70 + "Windows 2001.1 SP1", /* Windows Server 2003 SP1 - Added 03/2006 */ 71 + "Windows 2006", /* Windows Vista - Added 03/2006 */ 75 72 76 73 /* Feature Group Strings */ 77 74
+80 -36
drivers/acpi/video.c
··· 33 33 #include <linux/seq_file.h> 34 34 35 35 #include <linux/backlight.h> 36 + #include <linux/video_output.h> 36 37 #include <asm/uaccess.h> 37 38 38 39 #include <acpi/acpi_bus.h> ··· 170 169 struct acpi_device *dev; 171 170 struct acpi_video_device_brightness *brightness; 172 171 struct backlight_device *backlight; 172 + struct output_device *output_dev; 173 173 }; 174 174 175 175 /* bus */ ··· 274 272 u32 level_current, u32 event); 275 273 static void acpi_video_switch_brightness(struct acpi_video_device *device, 276 274 int event); 275 + static int acpi_video_device_get_state(struct acpi_video_device *device, 276 + unsigned long *state); 277 + static int acpi_video_output_get(struct output_device *od); 278 + static int acpi_video_device_set_state(struct acpi_video_device *device, int state); 277 279 278 280 /*backlight device sysfs support*/ 279 281 static int acpi_video_get_brightness(struct backlight_device *bd) ··· 303 297 .update_status = acpi_video_set_brightness, 304 298 }; 305 299 300 + /*video output device sysfs support*/ 301 + static int acpi_video_output_get(struct output_device *od) 302 + { 303 + unsigned long state; 304 + struct acpi_video_device *vd = 305 + (struct acpi_video_device *)class_get_devdata(&od->class_dev); 306 + acpi_video_device_get_state(vd, &state); 307 + return (int)state; 308 + } 309 + 310 + static int acpi_video_output_set(struct output_device *od) 311 + { 312 + unsigned long state = od->request_state; 313 + struct acpi_video_device *vd= 314 + (struct acpi_video_device *)class_get_devdata(&od->class_dev); 315 + return acpi_video_device_set_state(vd, state); 316 + } 317 + 318 + static struct output_properties acpi_output_properties = { 319 + .set_state = acpi_video_output_set, 320 + .get_status = acpi_video_output_get, 321 + }; 306 322 /* -------------------------------------------------------------------------- 307 323 Video Management 308 324 -------------------------------------------------------------------------- */ ··· 559 531 560 532 static void acpi_video_device_find_cap(struct acpi_video_device *device) 561 533 { 562 - acpi_integer status; 563 534 acpi_handle h_dummy1; 564 535 int i; 565 536 u32 max_level = 0; ··· 592 565 device->cap._DSS = 1; 593 566 } 594 567 595 - status = acpi_video_device_lcd_query_levels(device, &obj); 568 + if (ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) { 596 569 597 - if (obj && obj->type == ACPI_TYPE_PACKAGE && obj->package.count >= 2) { 598 - int count = 0; 599 - union acpi_object *o; 570 + if (obj->package.count >= 2) { 571 + int count = 0; 572 + union acpi_object *o; 600 573 601 - br = kzalloc(sizeof(*br), GFP_KERNEL); 602 - if (!br) { 603 - printk(KERN_ERR "can't allocate memory\n"); 604 - } else { 605 - br->levels = kmalloc(obj->package.count * 606 - sizeof *(br->levels), GFP_KERNEL); 607 - if (!br->levels) 608 - goto out; 609 - 610 - for (i = 0; i < obj->package.count; i++) { 611 - o = (union acpi_object *)&obj->package. 612 - elements[i]; 613 - if (o->type != ACPI_TYPE_INTEGER) { 614 - printk(KERN_ERR PREFIX "Invalid data\n"); 615 - continue; 616 - } 617 - br->levels[count] = (u32) o->integer.value; 618 - if (br->levels[count] > max_level) 619 - max_level = br->levels[count]; 620 - count++; 621 - } 622 - out: 623 - if (count < 2) { 624 - kfree(br->levels); 625 - kfree(br); 574 + br = kzalloc(sizeof(*br), GFP_KERNEL); 575 + if (!br) { 576 + printk(KERN_ERR "can't allocate memory\n"); 626 577 } else { 627 - br->count = count; 628 - device->brightness = br; 629 - ACPI_DEBUG_PRINT((ACPI_DB_INFO, 630 - "found %d brightness levels\n", 631 - count)); 578 + br->levels = kmalloc(obj->package.count * 579 + sizeof *(br->levels), GFP_KERNEL); 580 + if (!br->levels) 581 + goto out; 582 + 583 + for (i = 0; i < obj->package.count; i++) { 584 + o = (union acpi_object *)&obj->package. 585 + elements[i]; 586 + if (o->type != ACPI_TYPE_INTEGER) { 587 + printk(KERN_ERR PREFIX "Invalid data\n"); 588 + continue; 589 + } 590 + br->levels[count] = (u32) o->integer.value; 591 + 592 + if (br->levels[count] > max_level) 593 + max_level = br->levels[count]; 594 + count++; 595 + } 596 + out: 597 + if (count < 2) { 598 + kfree(br->levels); 599 + kfree(br); 600 + } else { 601 + br->count = count; 602 + device->brightness = br; 603 + ACPI_DEBUG_PRINT((ACPI_DB_INFO, 604 + "found %d brightness levels\n", 605 + count)); 606 + } 632 607 } 633 608 } 609 + 610 + } else { 611 + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available LCD brightness level\n")); 634 612 } 635 613 636 614 kfree(obj); 637 615 638 - if (device->cap._BCL && device->cap._BCM && device->cap._BQC){ 616 + if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){ 639 617 unsigned long tmp; 640 618 static int count = 0; 641 619 char *name; ··· 656 624 device->backlight->props.brightness = (int)tmp; 657 625 backlight_update_status(device->backlight); 658 626 627 + kfree(name); 628 + } 629 + if (device->cap._DCS && device->cap._DSS){ 630 + static int count = 0; 631 + char *name; 632 + name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); 633 + if (!name) 634 + return; 635 + sprintf(name, "acpi_video%d", count++); 636 + device->output_dev = video_output_register(name, 637 + NULL, device, &acpi_output_properties); 659 638 kfree(name); 660 639 } 661 640 return; ··· 1712 1669 ACPI_DEVICE_NOTIFY, 1713 1670 acpi_video_device_notify); 1714 1671 backlight_device_unregister(device->backlight); 1672 + video_output_unregister(device->output_dev); 1715 1673 return 0; 1716 1674 } 1717 1675
+14
drivers/misc/Kconfig
··· 150 150 depends on X86 && ACPI 151 151 select BACKLIGHT_CLASS_DEVICE 152 152 select HWMON 153 + select NVRAM 153 154 ---help--- 154 155 This is a driver for the IBM and Lenovo ThinkPad laptops. It adds 155 156 support for Fn-Fx key combinations, Bluetooth control, video ··· 196 195 notifications when the bay lever is ejected or inserted. 197 196 198 197 If you are not sure, say Y here. 198 + 199 + config THINKPAD_ACPI_INPUT_ENABLED 200 + bool "Enable input layer support by default" 201 + depends on THINKPAD_ACPI 202 + default y 203 + ---help--- 204 + Enables hot key handling over the input layer by default. If unset, 205 + the driver does not enable any hot key handling by default, and also 206 + starts up with a mostly empty keymap. 207 + 208 + If you are not sure, say Y here. Say N to retain the deprecated 209 + behavior of ibm-acpi, and thinkpad-acpi for kernels up to 2.6.21. 210 + 199 211 200 212 endif # MISC_DEVICES
+308 -60
drivers/misc/sony-laptop.c
··· 142 142 int key; 143 143 }; 144 144 145 - /* Correspondance table between sonypi events and input layer events */ 146 - static struct { 147 - int sonypiev; 148 - int inputev; 149 - } sony_laptop_inputkeys[] = { 150 - { SONYPI_EVENT_CAPTURE_PRESSED, KEY_CAMERA }, 151 - { SONYPI_EVENT_FNKEY_ONLY, KEY_FN }, 152 - { SONYPI_EVENT_FNKEY_ESC, KEY_FN_ESC }, 153 - { SONYPI_EVENT_FNKEY_F1, KEY_FN_F1 }, 154 - { SONYPI_EVENT_FNKEY_F2, KEY_FN_F2 }, 155 - { SONYPI_EVENT_FNKEY_F3, KEY_FN_F3 }, 156 - { SONYPI_EVENT_FNKEY_F4, KEY_FN_F4 }, 157 - { SONYPI_EVENT_FNKEY_F5, KEY_FN_F5 }, 158 - { SONYPI_EVENT_FNKEY_F6, KEY_FN_F6 }, 159 - { SONYPI_EVENT_FNKEY_F7, KEY_FN_F7 }, 160 - { SONYPI_EVENT_FNKEY_F8, KEY_FN_F8 }, 161 - { SONYPI_EVENT_FNKEY_F9, KEY_FN_F9 }, 162 - { SONYPI_EVENT_FNKEY_F10, KEY_FN_F10 }, 163 - { SONYPI_EVENT_FNKEY_F11, KEY_FN_F11 }, 164 - { SONYPI_EVENT_FNKEY_F12, KEY_FN_F12 }, 165 - { SONYPI_EVENT_FNKEY_1, KEY_FN_1 }, 166 - { SONYPI_EVENT_FNKEY_2, KEY_FN_2 }, 167 - { SONYPI_EVENT_FNKEY_D, KEY_FN_D }, 168 - { SONYPI_EVENT_FNKEY_E, KEY_FN_E }, 169 - { SONYPI_EVENT_FNKEY_F, KEY_FN_F }, 170 - { SONYPI_EVENT_FNKEY_S, KEY_FN_S }, 171 - { SONYPI_EVENT_FNKEY_B, KEY_FN_B }, 172 - { SONYPI_EVENT_BLUETOOTH_PRESSED, KEY_BLUE }, 173 - { SONYPI_EVENT_BLUETOOTH_ON, KEY_BLUE }, 174 - { SONYPI_EVENT_PKEY_P1, KEY_PROG1 }, 175 - { SONYPI_EVENT_PKEY_P2, KEY_PROG2 }, 176 - { SONYPI_EVENT_PKEY_P3, KEY_PROG3 }, 177 - { SONYPI_EVENT_BACK_PRESSED, KEY_BACK }, 178 - { SONYPI_EVENT_HELP_PRESSED, KEY_HELP }, 179 - { SONYPI_EVENT_ZOOM_PRESSED, KEY_ZOOM }, 180 - { SONYPI_EVENT_THUMBPHRASE_PRESSED, BTN_THUMB }, 181 - { 0, 0 }, 145 + /* Correspondance table between sonypi events 146 + * and input layer indexes in the keymap 147 + */ 148 + static int sony_laptop_input_index[] = { 149 + -1, /* no event */ 150 + -1, /* SONYPI_EVENT_JOGDIAL_DOWN */ 151 + -1, /* SONYPI_EVENT_JOGDIAL_UP */ 152 + -1, /* SONYPI_EVENT_JOGDIAL_DOWN_PRESSED */ 153 + -1, /* SONYPI_EVENT_JOGDIAL_UP_PRESSED */ 154 + -1, /* SONYPI_EVENT_JOGDIAL_PRESSED */ 155 + -1, /* SONYPI_EVENT_JOGDIAL_RELEASED */ 156 + 0, /* SONYPI_EVENT_CAPTURE_PRESSED */ 157 + 1, /* SONYPI_EVENT_CAPTURE_RELEASED */ 158 + 2, /* SONYPI_EVENT_CAPTURE_PARTIALPRESSED */ 159 + 3, /* SONYPI_EVENT_CAPTURE_PARTIALRELEASED */ 160 + 4, /* SONYPI_EVENT_FNKEY_ESC */ 161 + 5, /* SONYPI_EVENT_FNKEY_F1 */ 162 + 6, /* SONYPI_EVENT_FNKEY_F2 */ 163 + 7, /* SONYPI_EVENT_FNKEY_F3 */ 164 + 8, /* SONYPI_EVENT_FNKEY_F4 */ 165 + 9, /* SONYPI_EVENT_FNKEY_F5 */ 166 + 10, /* SONYPI_EVENT_FNKEY_F6 */ 167 + 11, /* SONYPI_EVENT_FNKEY_F7 */ 168 + 12, /* SONYPI_EVENT_FNKEY_F8 */ 169 + 13, /* SONYPI_EVENT_FNKEY_F9 */ 170 + 14, /* SONYPI_EVENT_FNKEY_F10 */ 171 + 15, /* SONYPI_EVENT_FNKEY_F11 */ 172 + 16, /* SONYPI_EVENT_FNKEY_F12 */ 173 + 17, /* SONYPI_EVENT_FNKEY_1 */ 174 + 18, /* SONYPI_EVENT_FNKEY_2 */ 175 + 19, /* SONYPI_EVENT_FNKEY_D */ 176 + 20, /* SONYPI_EVENT_FNKEY_E */ 177 + 21, /* SONYPI_EVENT_FNKEY_F */ 178 + 22, /* SONYPI_EVENT_FNKEY_S */ 179 + 23, /* SONYPI_EVENT_FNKEY_B */ 180 + 24, /* SONYPI_EVENT_BLUETOOTH_PRESSED */ 181 + 25, /* SONYPI_EVENT_PKEY_P1 */ 182 + 26, /* SONYPI_EVENT_PKEY_P2 */ 183 + 27, /* SONYPI_EVENT_PKEY_P3 */ 184 + 28, /* SONYPI_EVENT_BACK_PRESSED */ 185 + -1, /* SONYPI_EVENT_LID_CLOSED */ 186 + -1, /* SONYPI_EVENT_LID_OPENED */ 187 + 29, /* SONYPI_EVENT_BLUETOOTH_ON */ 188 + 30, /* SONYPI_EVENT_BLUETOOTH_OFF */ 189 + 31, /* SONYPI_EVENT_HELP_PRESSED */ 190 + 32, /* SONYPI_EVENT_FNKEY_ONLY */ 191 + 33, /* SONYPI_EVENT_JOGDIAL_FAST_DOWN */ 192 + 34, /* SONYPI_EVENT_JOGDIAL_FAST_UP */ 193 + 35, /* SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED */ 194 + 36, /* SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED */ 195 + 37, /* SONYPI_EVENT_JOGDIAL_VFAST_DOWN */ 196 + 38, /* SONYPI_EVENT_JOGDIAL_VFAST_UP */ 197 + 39, /* SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED */ 198 + 40, /* SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED */ 199 + 41, /* SONYPI_EVENT_ZOOM_PRESSED */ 200 + 42, /* SONYPI_EVENT_THUMBPHRASE_PRESSED */ 201 + 43, /* SONYPI_EVENT_MEYE_FACE */ 202 + 44, /* SONYPI_EVENT_MEYE_OPPOSITE */ 203 + 45, /* SONYPI_EVENT_MEMORYSTICK_INSERT */ 204 + 46, /* SONYPI_EVENT_MEMORYSTICK_EJECT */ 205 + -1, /* SONYPI_EVENT_ANYBUTTON_RELEASED */ 206 + -1, /* SONYPI_EVENT_BATTERY_INSERT */ 207 + -1, /* SONYPI_EVENT_BATTERY_REMOVE */ 208 + -1, /* SONYPI_EVENT_FNKEY_RELEASED */ 209 + 47, /* SONYPI_EVENT_WIRELESS_ON */ 210 + 48, /* SONYPI_EVENT_WIRELESS_OFF */ 211 + }; 212 + 213 + static int sony_laptop_input_keycode_map[] = { 214 + KEY_CAMERA, /* 0 SONYPI_EVENT_CAPTURE_PRESSED */ 215 + KEY_RESERVED, /* 1 SONYPI_EVENT_CAPTURE_RELEASED */ 216 + KEY_RESERVED, /* 2 SONYPI_EVENT_CAPTURE_PARTIALPRESSED */ 217 + KEY_RESERVED, /* 3 SONYPI_EVENT_CAPTURE_PARTIALRELEASED */ 218 + KEY_FN_ESC, /* 4 SONYPI_EVENT_FNKEY_ESC */ 219 + KEY_FN_F1, /* 5 SONYPI_EVENT_FNKEY_F1 */ 220 + KEY_FN_F2, /* 6 SONYPI_EVENT_FNKEY_F2 */ 221 + KEY_FN_F3, /* 7 SONYPI_EVENT_FNKEY_F3 */ 222 + KEY_FN_F4, /* 8 SONYPI_EVENT_FNKEY_F4 */ 223 + KEY_FN_F5, /* 9 SONYPI_EVENT_FNKEY_F5 */ 224 + KEY_FN_F6, /* 10 SONYPI_EVENT_FNKEY_F6 */ 225 + KEY_FN_F7, /* 11 SONYPI_EVENT_FNKEY_F7 */ 226 + KEY_FN_F8, /* 12 SONYPI_EVENT_FNKEY_F8 */ 227 + KEY_FN_F9, /* 13 SONYPI_EVENT_FNKEY_F9 */ 228 + KEY_FN_F10, /* 14 SONYPI_EVENT_FNKEY_F10 */ 229 + KEY_FN_F11, /* 15 SONYPI_EVENT_FNKEY_F11 */ 230 + KEY_FN_F12, /* 16 SONYPI_EVENT_FNKEY_F12 */ 231 + KEY_FN_F1, /* 17 SONYPI_EVENT_FNKEY_1 */ 232 + KEY_FN_F2, /* 18 SONYPI_EVENT_FNKEY_2 */ 233 + KEY_FN_D, /* 19 SONYPI_EVENT_FNKEY_D */ 234 + KEY_FN_E, /* 20 SONYPI_EVENT_FNKEY_E */ 235 + KEY_FN_F, /* 21 SONYPI_EVENT_FNKEY_F */ 236 + KEY_FN_S, /* 22 SONYPI_EVENT_FNKEY_S */ 237 + KEY_FN_B, /* 23 SONYPI_EVENT_FNKEY_B */ 238 + KEY_BLUETOOTH, /* 24 SONYPI_EVENT_BLUETOOTH_PRESSED */ 239 + KEY_PROG1, /* 25 SONYPI_EVENT_PKEY_P1 */ 240 + KEY_PROG2, /* 26 SONYPI_EVENT_PKEY_P2 */ 241 + KEY_PROG3, /* 27 SONYPI_EVENT_PKEY_P3 */ 242 + KEY_BACK, /* 28 SONYPI_EVENT_BACK_PRESSED */ 243 + KEY_BLUETOOTH, /* 29 SONYPI_EVENT_BLUETOOTH_ON */ 244 + KEY_BLUETOOTH, /* 30 SONYPI_EVENT_BLUETOOTH_OFF */ 245 + KEY_HELP, /* 31 SONYPI_EVENT_HELP_PRESSED */ 246 + KEY_FN, /* 32 SONYPI_EVENT_FNKEY_ONLY */ 247 + KEY_RESERVED, /* 33 SONYPI_EVENT_JOGDIAL_FAST_DOWN */ 248 + KEY_RESERVED, /* 34 SONYPI_EVENT_JOGDIAL_FAST_UP */ 249 + KEY_RESERVED, /* 35 SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED */ 250 + KEY_RESERVED, /* 36 SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED */ 251 + KEY_RESERVED, /* 37 SONYPI_EVENT_JOGDIAL_VFAST_DOWN */ 252 + KEY_RESERVED, /* 38 SONYPI_EVENT_JOGDIAL_VFAST_UP */ 253 + KEY_RESERVED, /* 39 SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED */ 254 + KEY_RESERVED, /* 40 SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED */ 255 + KEY_ZOOM, /* 41 SONYPI_EVENT_ZOOM_PRESSED */ 256 + BTN_THUMB, /* 42 SONYPI_EVENT_THUMBPHRASE_PRESSED */ 257 + KEY_RESERVED, /* 43 SONYPI_EVENT_MEYE_FACE */ 258 + KEY_RESERVED, /* 44 SONYPI_EVENT_MEYE_OPPOSITE */ 259 + KEY_RESERVED, /* 45 SONYPI_EVENT_MEMORYSTICK_INSERT */ 260 + KEY_RESERVED, /* 46 SONYPI_EVENT_MEMORYSTICK_EJECT */ 261 + KEY_WLAN, /* 47 SONYPI_EVENT_WIRELESS_ON */ 262 + KEY_WLAN, /* 48 SONYPI_EVENT_WIRELESS_OFF */ 182 263 }; 183 264 184 265 /* release buttons after a short delay if pressed */ ··· 283 202 struct input_dev *jog_dev = sony_laptop_input.jog_dev; 284 203 struct input_dev *key_dev = sony_laptop_input.key_dev; 285 204 struct sony_laptop_keypress kp = { NULL }; 286 - int i; 287 205 288 206 if (event == SONYPI_EVENT_FNKEY_RELEASED) { 289 207 /* Nothing, not all VAIOs generate this event */ ··· 311 231 break; 312 232 313 233 default: 314 - for (i = 0; sony_laptop_inputkeys[i].sonypiev; i++) 315 - if (event == sony_laptop_inputkeys[i].sonypiev) { 234 + if (event > ARRAY_SIZE (sony_laptop_input_keycode_map)) { 235 + dprintk("sony_laptop_report_input_event, event not known: %d\n", event); 236 + break; 237 + } 238 + if (sony_laptop_input_index[event] != -1) { 239 + kp.key = sony_laptop_input_keycode_map[sony_laptop_input_index[event]]; 240 + if (kp.key != KEY_UNKNOWN) 316 241 kp.dev = key_dev; 317 - kp.key = sony_laptop_inputkeys[i].inputev; 318 - break; 319 - } 242 + } 320 243 break; 321 244 } 322 245 323 246 if (kp.dev) { 324 247 input_report_key(kp.dev, kp.key, 1); 248 + /* we emit the scancode so we can always remap the key */ 249 + input_event(kp.dev, EV_MSC, MSC_SCAN, event); 325 250 input_sync(kp.dev); 326 251 kfifo_put(sony_laptop_input.fifo, 327 252 (unsigned char *)&kp, sizeof(kp)); ··· 381 296 key_dev->id.vendor = PCI_VENDOR_ID_SONY; 382 297 383 298 /* Initialize the Input Drivers: special keys */ 384 - key_dev->evbit[0] = BIT(EV_KEY); 385 - for (i = 0; sony_laptop_inputkeys[i].sonypiev; i++) 386 - if (sony_laptop_inputkeys[i].inputev) 387 - set_bit(sony_laptop_inputkeys[i].inputev, 388 - key_dev->keybit); 299 + set_bit(EV_KEY, key_dev->evbit); 300 + set_bit(EV_MSC, key_dev->evbit); 301 + set_bit(MSC_SCAN, key_dev->mscbit); 302 + key_dev->keycodesize = sizeof(sony_laptop_input_keycode_map[0]); 303 + key_dev->keycodemax = ARRAY_SIZE(sony_laptop_input_keycode_map); 304 + key_dev->keycode = &sony_laptop_input_keycode_map; 305 + for (i = 0; i < ARRAY_SIZE(sony_laptop_input_keycode_map); i++) { 306 + if (sony_laptop_input_keycode_map[i] != KEY_RESERVED) { 307 + set_bit(sony_laptop_input_keycode_map[i], 308 + key_dev->keybit); 309 + } 310 + } 389 311 390 312 error = input_register_device(key_dev); 391 313 if (error) ··· 579 487 SNC_HANDLE_NAMES(lanpower_get, "GLNP"); 580 488 SNC_HANDLE_NAMES(lanpower_set, "LNPW"); 581 489 490 + SNC_HANDLE_NAMES(lidstate_get, "GLID"); 491 + 492 + SNC_HANDLE_NAMES(indicatorlamp_get, "GILS"); 493 + SNC_HANDLE_NAMES(indicatorlamp_set, "SILS"); 494 + 495 + SNC_HANDLE_NAMES(gainbass_get, "GMGB"); 496 + SNC_HANDLE_NAMES(gainbass_set, "CMGB"); 497 + 582 498 SNC_HANDLE_NAMES(PID_get, "GPID"); 583 499 584 500 SNC_HANDLE_NAMES(CTR_get, "GCTR"); ··· 607 507 boolean_validate, 0), 608 508 SNC_HANDLE(lanpower, snc_lanpower_get, snc_lanpower_set, 609 509 boolean_validate, 1), 510 + SNC_HANDLE(lidstate, snc_lidstate_get, NULL, 511 + boolean_validate, 0), 512 + SNC_HANDLE(indicatorlamp, snc_indicatorlamp_get, snc_indicatorlamp_set, 513 + boolean_validate, 0), 514 + SNC_HANDLE(gainbass, snc_gainbass_get, snc_gainbass_set, 515 + boolean_validate, 0), 610 516 /* unknown methods */ 611 517 SNC_HANDLE(PID, snc_PID_get, NULL, NULL, 1), 612 518 SNC_HANDLE(CTR, snc_CTR_get, snc_CTR_set, NULL, 1), ··· 795 689 }; 796 690 797 691 /* 692 + * New SNC-only Vaios event mapping to driver known keys 693 + */ 694 + struct sony_nc_event { 695 + u8 data; 696 + u8 event; 697 + }; 698 + 699 + static struct sony_nc_event *sony_nc_events; 700 + 701 + /* Vaio C* --maybe also FE*, N* and AR* ?-- special init sequence 702 + * for Fn keys 703 + */ 704 + static int sony_nc_C_enable(struct dmi_system_id *id) 705 + { 706 + int result = 0; 707 + 708 + printk(KERN_NOTICE DRV_PFX "detected %s\n", id->ident); 709 + 710 + sony_nc_events = id->driver_data; 711 + 712 + if (acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0x4, &result) < 0 713 + || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x2, &result) < 0 714 + || acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0x10, &result) < 0 715 + || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x0, &result) < 0 716 + || acpi_callsetfunc(sony_nc_acpi_handle, "SN03", 0x2, &result) < 0 717 + || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x101, &result) < 0) { 718 + printk(KERN_WARNING DRV_PFX "failed to initialize SNC, some " 719 + "functionalities may be missing\n"); 720 + return 1; 721 + } 722 + return 0; 723 + } 724 + 725 + static struct sony_nc_event sony_C_events[] = { 726 + { 0x81, SONYPI_EVENT_FNKEY_F1 }, 727 + { 0x01, SONYPI_EVENT_FNKEY_RELEASED }, 728 + { 0x85, SONYPI_EVENT_FNKEY_F5 }, 729 + { 0x05, SONYPI_EVENT_FNKEY_RELEASED }, 730 + { 0x86, SONYPI_EVENT_FNKEY_F6 }, 731 + { 0x06, SONYPI_EVENT_FNKEY_RELEASED }, 732 + { 0x87, SONYPI_EVENT_FNKEY_F7 }, 733 + { 0x07, SONYPI_EVENT_FNKEY_RELEASED }, 734 + { 0x8A, SONYPI_EVENT_FNKEY_F10 }, 735 + { 0x0A, SONYPI_EVENT_FNKEY_RELEASED }, 736 + { 0x8C, SONYPI_EVENT_FNKEY_F12 }, 737 + { 0x0C, SONYPI_EVENT_FNKEY_RELEASED }, 738 + { 0, 0 }, 739 + }; 740 + 741 + /* SNC-only model map */ 742 + struct dmi_system_id sony_nc_ids[] = { 743 + { 744 + .ident = "Sony Vaio FE Series", 745 + .callback = sony_nc_C_enable, 746 + .driver_data = sony_C_events, 747 + .matches = { 748 + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), 749 + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FE"), 750 + }, 751 + }, 752 + { 753 + .ident = "Sony Vaio C Series", 754 + .callback = sony_nc_C_enable, 755 + .driver_data = sony_C_events, 756 + .matches = { 757 + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), 758 + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-C"), 759 + }, 760 + }, 761 + { } 762 + }; 763 + 764 + /* 798 765 * ACPI callbacks 799 766 */ 800 767 static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) 801 768 { 802 - dprintk("sony_acpi_notify, event: %d\n", event); 803 - sony_laptop_report_input_event(event); 804 - acpi_bus_generate_event(sony_nc_acpi_device, 1, event); 769 + struct sony_nc_event *evmap; 770 + u32 ev = event; 771 + int result; 772 + 773 + if (ev == 0x92) { 774 + /* read the key pressed from EC.GECR 775 + * A call to SN07 with 0x0202 will do it as well respecting 776 + * the current protocol on different OSes 777 + * 778 + * Note: the path for GECR may be 779 + * \_SB.PCI0.LPCB.EC (C, FE, AR, N and friends) 780 + * \_SB.PCI0.PIB.EC0 (VGN-FR notifications are sent directly, no GECR) 781 + * 782 + * TODO: we may want to do the same for the older GHKE -need 783 + * dmi list- so this snippet may become one more callback. 784 + */ 785 + if (acpi_callsetfunc(handle, "SN07", 0x0202, &result) < 0) 786 + dprintk("sony_acpi_notify, unable to decode event 0x%.2x\n", ev); 787 + else 788 + ev = result & 0xFF; 789 + } 790 + 791 + if (sony_nc_events) 792 + for (evmap = sony_nc_events; evmap->event; evmap++) { 793 + if (evmap->data == ev) { 794 + ev = evmap->event; 795 + break; 796 + } 797 + } 798 + 799 + dprintk("sony_acpi_notify, event: 0x%.2x\n", ev); 800 + sony_laptop_report_input_event(ev); 801 + acpi_bus_generate_event(sony_nc_acpi_device, 1, ev); 805 802 } 806 803 807 804 static acpi_status sony_walk_callback(acpi_handle handle, u32 level, ··· 941 732 break; 942 733 } 943 734 } 735 + 736 + /* re-initialize models with specific requirements */ 737 + dmi_check_system(sony_nc_ids); 738 + 944 739 return 0; 945 740 } 946 741 ··· 963 750 964 751 sony_nc_acpi_handle = device->handle; 965 752 753 + /* read device status */ 754 + result = acpi_bus_get_status(device); 755 + /* bail IFF the above call was successful and the device is not present */ 756 + if (!result && !device->status.present) { 757 + dprintk("Device not present\n"); 758 + result = -ENODEV; 759 + goto outwalk; 760 + } 761 + 966 762 if (debug) { 967 763 status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_nc_acpi_handle, 968 764 1, sony_walk_callback, NULL, NULL); ··· 980 758 result = -ENODEV; 981 759 goto outwalk; 982 760 } 761 + } 762 + 763 + /* try to _INI the device if such method exists (ACPI spec 3.0-6.5.1 764 + * should be respected as we already checked for the device presence above */ 765 + if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, METHOD_NAME__INI, &handle))) { 766 + dprintk("Invoking _INI\n"); 767 + if (ACPI_FAILURE(acpi_evaluate_object(sony_nc_acpi_handle, METHOD_NAME__INI, 768 + NULL, NULL))) 769 + dprintk("_INI Method failed\n"); 983 770 } 984 771 985 772 /* setup input devices and helper fifo */ ··· 1003 772 ACPI_DEVICE_NOTIFY, 1004 773 sony_acpi_notify, NULL); 1005 774 if (ACPI_FAILURE(status)) { 1006 - printk(KERN_WARNING DRV_PFX "unable to install notify handler\n"); 775 + printk(KERN_WARNING DRV_PFX "unable to install notify handler (%u)\n", status); 1007 776 result = -ENODEV; 1008 777 goto outinput; 1009 778 } ··· 1025 794 } 1026 795 1027 796 } 797 + 798 + /* initialize models with specific requirements */ 799 + dmi_check_system(sony_nc_ids); 1028 800 1029 801 result = sony_pf_add(); 1030 802 if (result) ··· 1142 908 #define SONYPI_DEVICE_TYPE2 0x00000002 1143 909 #define SONYPI_DEVICE_TYPE3 0x00000004 1144 910 1145 - #define SONY_PIC_EV_MASK 0xff 911 + #define SONYPI_TYPE1_OFFSET 0x04 912 + #define SONYPI_TYPE2_OFFSET 0x12 913 + #define SONYPI_TYPE3_OFFSET 0x12 1146 914 1147 915 struct sony_pic_ioport { 1148 916 struct acpi_resource_io io; ··· 1158 922 1159 923 struct sony_pic_dev { 1160 924 int model; 925 + u16 evport_offset; 1161 926 u8 camera_power; 1162 927 u8 bluetooth_power; 1163 928 u8 wwan_power; ··· 2236 1999 static irqreturn_t sony_pic_irq(int irq, void *dev_id) 2237 2000 { 2238 2001 int i, j; 2239 - u32 port_val = 0; 2240 2002 u8 ev = 0; 2241 2003 u8 data_mask = 0; 2242 2004 u8 device_event = 0; 2243 2005 2244 2006 struct sony_pic_dev *dev = (struct sony_pic_dev *) dev_id; 2245 2007 2246 - acpi_os_read_port(dev->cur_ioport->io.minimum, &port_val, 2247 - dev->cur_ioport->io.address_length); 2248 - ev = port_val & SONY_PIC_EV_MASK; 2249 - data_mask = 0xff & (port_val >> (dev->cur_ioport->io.address_length - 8)); 2008 + ev = inb_p(dev->cur_ioport->io.minimum); 2009 + data_mask = inb_p(dev->cur_ioport->io.minimum + dev->evport_offset); 2250 2010 2251 - dprintk("event (0x%.8x [%.2x] [%.2x]) at port 0x%.4x\n", 2252 - port_val, ev, data_mask, dev->cur_ioport->io.minimum); 2011 + dprintk("event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n", 2012 + ev, data_mask, dev->cur_ioport->io.minimum, dev->evport_offset); 2253 2013 2254 2014 if (ev == 0x00 || ev == 0xff) 2255 2015 return IRQ_HANDLED; ··· 2336 2102 strcpy(acpi_device_class(device), "sony/hotkey"); 2337 2103 spic_dev.model = sony_pic_detect_device_type(); 2338 2104 mutex_init(&spic_dev.lock); 2105 + 2106 + /* model specific characteristics */ 2107 + switch(spic_dev.model) { 2108 + case SONYPI_DEVICE_TYPE1: 2109 + spic_dev.evport_offset = SONYPI_TYPE1_OFFSET; 2110 + break; 2111 + case SONYPI_DEVICE_TYPE3: 2112 + spic_dev.evport_offset = SONYPI_TYPE3_OFFSET; 2113 + break; 2114 + case SONYPI_DEVICE_TYPE2: 2115 + default: 2116 + spic_dev.evport_offset = SONYPI_TYPE2_OFFSET; 2117 + break; 2118 + } 2339 2119 2340 2120 /* read _PRS resources */ 2341 2121 result = sony_pic_possible_resources(device);
+529 -79
drivers/misc/thinkpad_acpi.c
··· 21 21 * 02110-1301, USA. 22 22 */ 23 23 24 - #define IBM_VERSION "0.14" 25 - #define TPACPI_SYSFS_VERSION 0x000100 24 + #define IBM_VERSION "0.15" 25 + #define TPACPI_SYSFS_VERSION 0x010000 26 26 27 27 /* 28 28 * Changelog: ··· 92 92 /* Please remove this in year 2009 */ 93 93 MODULE_ALIAS("ibm_acpi"); 94 94 95 + /* 96 + * DMI matching for module autoloading 97 + * 98 + * See http://thinkwiki.org/wiki/List_of_DMI_IDs 99 + * See http://thinkwiki.org/wiki/BIOS_Upgrade_Downloads 100 + * 101 + * Only models listed in thinkwiki will be supported, so add yours 102 + * if it is not there yet. 103 + */ 104 + #define IBM_BIOS_MODULE_ALIAS(__type) \ 105 + MODULE_ALIAS("dmi:bvnIBM:bvr" __type "ET??WW") 106 + 107 + /* Non-ancient thinkpads */ 108 + MODULE_ALIAS("dmi:bvnIBM:*:svnIBM:*:pvrThinkPad*:rvnIBM:*"); 109 + MODULE_ALIAS("dmi:bvnLENOVO:*:svnLENOVO:*:pvrThinkPad*:rvnLENOVO:*"); 110 + 111 + /* Ancient thinkpad BIOSes have to be identified by 112 + * BIOS type or model number, and there are far less 113 + * BIOS types than model numbers... */ 114 + IBM_BIOS_MODULE_ALIAS("I[B,D,H,I,M,N,O,T,W,V,Y,Z]"); 115 + IBM_BIOS_MODULE_ALIAS("1[0,3,6,8,A-G,I,K,M-P,S,T]"); 116 + IBM_BIOS_MODULE_ALIAS("K[U,X-Z]"); 117 + 95 118 #define __unused __attribute__ ((unused)) 96 119 97 120 /**************************************************************************** ··· 129 106 * ACPI basic handles 130 107 */ 131 108 132 - static acpi_handle root_handle = NULL; 109 + static acpi_handle root_handle; 133 110 134 111 #define IBM_HANDLE(object, parent, paths...) \ 135 112 static acpi_handle object##_handle; \ ··· 510 487 /**************************************************************************** 511 488 **************************************************************************** 512 489 * 513 - * Device model: hwmon and platform 490 + * Device model: input, hwmon and platform 514 491 * 515 492 **************************************************************************** 516 493 ****************************************************************************/ 517 494 518 - static struct platform_device *tpacpi_pdev = NULL; 519 - static struct class_device *tpacpi_hwmon = NULL; 495 + static struct platform_device *tpacpi_pdev; 496 + static struct class_device *tpacpi_hwmon; 497 + static struct input_dev *tpacpi_inputdev; 498 + 499 + 500 + static int tpacpi_resume_handler(struct platform_device *pdev) 501 + { 502 + struct ibm_struct *ibm, *itmp; 503 + 504 + list_for_each_entry_safe(ibm, itmp, 505 + &tpacpi_all_drivers, 506 + all_drivers) { 507 + if (ibm->resume) 508 + (ibm->resume)(); 509 + } 510 + 511 + return 0; 512 + } 520 513 521 514 static struct platform_driver tpacpi_pdriver = { 522 515 .driver = { 523 516 .name = IBM_DRVR_NAME, 524 517 .owner = THIS_MODULE, 525 518 }, 519 + .resume = tpacpi_resume_handler, 526 520 }; 527 521 528 522 ··· 717 677 printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION); 718 678 printk(IBM_INFO "%s\n", IBM_URL); 719 679 720 - if (ibm_thinkpad_ec_found) 721 - printk(IBM_INFO "ThinkPad EC firmware %s\n", 722 - ibm_thinkpad_ec_found); 680 + printk(IBM_INFO "ThinkPad BIOS %s, EC %s\n", 681 + (thinkpad_id.bios_version_str) ? 682 + thinkpad_id.bios_version_str : "unknown", 683 + (thinkpad_id.ec_version_str) ? 684 + thinkpad_id.ec_version_str : "unknown"); 685 + 686 + if (thinkpad_id.vendor && thinkpad_id.model_str) 687 + printk(IBM_INFO "%s %s\n", 688 + (thinkpad_id.vendor == PCI_VENDOR_ID_IBM) ? 689 + "IBM" : ((thinkpad_id.vendor == 690 + PCI_VENDOR_ID_LENOVO) ? 691 + "Lenovo" : "Unknown vendor"), 692 + thinkpad_id.model_str); 723 693 724 694 return 0; 725 695 } ··· 754 704 */ 755 705 756 706 static int hotkey_orig_status; 757 - static int hotkey_orig_mask; 707 + static u32 hotkey_orig_mask; 708 + static u32 hotkey_all_mask; 709 + static u32 hotkey_reserved_mask; 758 710 759 - static struct attribute_set *hotkey_dev_attributes = NULL; 711 + static u16 *hotkey_keycode_map; 712 + 713 + static struct attribute_set *hotkey_dev_attributes; 714 + 715 + static int hotkey_get_wlsw(int *status) 716 + { 717 + if (!acpi_evalf(hkey_handle, status, "WLSW", "d")) 718 + return -EIO; 719 + return 0; 720 + } 760 721 761 722 /* sysfs hotkey enable ------------------------------------------------- */ 762 723 static ssize_t hotkey_enable_show(struct device *dev, 763 724 struct device_attribute *attr, 764 725 char *buf) 765 726 { 766 - int res, status, mask; 727 + int res, status; 728 + u32 mask; 767 729 768 730 res = hotkey_get(&status, &mask); 769 731 if (res) ··· 789 727 const char *buf, size_t count) 790 728 { 791 729 unsigned long t; 792 - int res, status, mask; 730 + int res, status; 731 + u32 mask; 793 732 794 733 if (parse_strtoul(buf, 1, &t)) 795 734 return -EINVAL; ··· 811 748 struct device_attribute *attr, 812 749 char *buf) 813 750 { 814 - int res, status, mask; 751 + int res, status; 752 + u32 mask; 815 753 816 754 res = hotkey_get(&status, &mask); 817 755 if (res) 818 756 return res; 819 757 820 - return snprintf(buf, PAGE_SIZE, "0x%04x\n", mask); 758 + return snprintf(buf, PAGE_SIZE, "0x%08x\n", mask); 821 759 } 822 760 823 761 static ssize_t hotkey_mask_store(struct device *dev, ··· 826 762 const char *buf, size_t count) 827 763 { 828 764 unsigned long t; 829 - int res, status, mask; 765 + int res, status; 766 + u32 mask; 830 767 831 - if (parse_strtoul(buf, 0xffff, &t)) 768 + if (parse_strtoul(buf, 0xffffffffUL, &t)) 832 769 return -EINVAL; 833 770 834 771 res = hotkey_get(&status, &mask); ··· 859 794 struct device_attribute *attr, 860 795 char *buf) 861 796 { 862 - return snprintf(buf, PAGE_SIZE, "0x%04x\n", hotkey_orig_mask); 797 + return snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_orig_mask); 863 798 } 864 799 865 800 static struct device_attribute dev_attr_hotkey_bios_mask = 866 801 __ATTR(hotkey_bios_mask, S_IRUGO, hotkey_bios_mask_show, NULL); 802 + 803 + /* sysfs hotkey all_mask ----------------------------------------------- */ 804 + static ssize_t hotkey_all_mask_show(struct device *dev, 805 + struct device_attribute *attr, 806 + char *buf) 807 + { 808 + return snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_all_mask); 809 + } 810 + 811 + static struct device_attribute dev_attr_hotkey_all_mask = 812 + __ATTR(hotkey_all_mask, S_IRUGO, hotkey_all_mask_show, NULL); 813 + 814 + /* sysfs hotkey recommended_mask --------------------------------------- */ 815 + static ssize_t hotkey_recommended_mask_show(struct device *dev, 816 + struct device_attribute *attr, 817 + char *buf) 818 + { 819 + return snprintf(buf, PAGE_SIZE, "0x%08x\n", 820 + hotkey_all_mask & ~hotkey_reserved_mask); 821 + } 822 + 823 + static struct device_attribute dev_attr_hotkey_recommended_mask = 824 + __ATTR(hotkey_recommended_mask, S_IRUGO, 825 + hotkey_recommended_mask_show, NULL); 826 + 827 + /* sysfs hotkey radio_sw ----------------------------------------------- */ 828 + static ssize_t hotkey_radio_sw_show(struct device *dev, 829 + struct device_attribute *attr, 830 + char *buf) 831 + { 832 + int res, s; 833 + res = hotkey_get_wlsw(&s); 834 + if (res < 0) 835 + return res; 836 + 837 + return snprintf(buf, PAGE_SIZE, "%d\n", !!s); 838 + } 839 + 840 + static struct device_attribute dev_attr_hotkey_radio_sw = 841 + __ATTR(hotkey_radio_sw, S_IRUGO, hotkey_radio_sw_show, NULL); 867 842 868 843 /* --------------------------------------------------------------------- */ 869 844 ··· 911 806 &dev_attr_hotkey_mask.attr, 912 807 &dev_attr_hotkey_bios_enabled.attr, 913 808 &dev_attr_hotkey_bios_mask.attr, 809 + &dev_attr_hotkey_all_mask.attr, 810 + &dev_attr_hotkey_recommended_mask.attr, 914 811 }; 915 812 916 813 static int __init hotkey_init(struct ibm_init_struct *iibm) 917 814 { 918 - int res; 815 + 816 + static u16 ibm_keycode_map[] __initdata = { 817 + /* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */ 818 + KEY_FN_F1, KEY_FN_F2, KEY_COFFEE, KEY_SLEEP, 819 + KEY_WLAN, KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8, 820 + KEY_FN_F9, KEY_FN_F10, KEY_FN_F11, KEY_SUSPEND, 821 + /* Scan codes 0x0C to 0x0F: Other ACPI HKEY hot keys */ 822 + KEY_UNKNOWN, /* 0x0C: FN+BACKSPACE */ 823 + KEY_UNKNOWN, /* 0x0D: FN+INSERT */ 824 + KEY_UNKNOWN, /* 0x0E: FN+DELETE */ 825 + KEY_RESERVED, /* 0x0F: FN+HOME (brightness up) */ 826 + /* Scan codes 0x10 to 0x1F: Extended ACPI HKEY hot keys */ 827 + KEY_RESERVED, /* 0x10: FN+END (brightness down) */ 828 + KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */ 829 + KEY_UNKNOWN, /* 0x12: FN+PGDOWN */ 830 + KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */ 831 + KEY_RESERVED, /* 0x14: VOLUME UP */ 832 + KEY_RESERVED, /* 0x15: VOLUME DOWN */ 833 + KEY_RESERVED, /* 0x16: MUTE */ 834 + KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */ 835 + /* (assignments unknown, please report if found) */ 836 + KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, 837 + KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, 838 + }; 839 + static u16 lenovo_keycode_map[] __initdata = { 840 + /* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */ 841 + KEY_FN_F1, KEY_COFFEE, KEY_BATTERY, KEY_SLEEP, 842 + KEY_WLAN, KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8, 843 + KEY_FN_F9, KEY_FN_F10, KEY_FN_F11, KEY_SUSPEND, 844 + /* Scan codes 0x0C to 0x0F: Other ACPI HKEY hot keys */ 845 + KEY_UNKNOWN, /* 0x0C: FN+BACKSPACE */ 846 + KEY_UNKNOWN, /* 0x0D: FN+INSERT */ 847 + KEY_UNKNOWN, /* 0x0E: FN+DELETE */ 848 + KEY_BRIGHTNESSUP, /* 0x0F: FN+HOME (brightness up) */ 849 + /* Scan codes 0x10 to 0x1F: Extended ACPI HKEY hot keys */ 850 + KEY_BRIGHTNESSDOWN, /* 0x10: FN+END (brightness down) */ 851 + KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */ 852 + KEY_UNKNOWN, /* 0x12: FN+PGDOWN */ 853 + KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */ 854 + KEY_RESERVED, /* 0x14: VOLUME UP */ 855 + KEY_RESERVED, /* 0x15: VOLUME DOWN */ 856 + KEY_RESERVED, /* 0x16: MUTE */ 857 + KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */ 858 + /* (assignments unknown, please report if found) */ 859 + KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, 860 + KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, 861 + }; 862 + 863 + #define TPACPI_HOTKEY_MAP_LEN ARRAY_SIZE(ibm_keycode_map) 864 + #define TPACPI_HOTKEY_MAP_SIZE sizeof(ibm_keycode_map) 865 + #define TPACPI_HOTKEY_MAP_TYPESIZE sizeof(ibm_keycode_map[0]) 866 + 867 + int res, i; 868 + int status; 919 869 920 870 vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n"); 871 + 872 + BUG_ON(!tpacpi_inputdev); 921 873 922 874 IBM_ACPIHANDLE_INIT(hkey); 923 875 mutex_init(&hotkey_mutex); ··· 986 824 str_supported(tp_features.hotkey)); 987 825 988 826 if (tp_features.hotkey) { 989 - hotkey_dev_attributes = create_attr_set(4, NULL); 827 + hotkey_dev_attributes = create_attr_set(7, NULL); 990 828 if (!hotkey_dev_attributes) 991 829 return -ENOMEM; 992 830 res = add_to_attr_set(hotkey_dev_attributes, ··· 1002 840 vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n", 1003 841 str_supported(tp_features.hotkey_mask)); 1004 842 843 + if (tp_features.hotkey_mask) { 844 + /* MHKA available in A31, R40, R40e, T4x, X31, and later */ 845 + if (!acpi_evalf(hkey_handle, &hotkey_all_mask, 846 + "MHKA", "qd")) 847 + hotkey_all_mask = 0x080cU; /* FN+F12, FN+F4, FN+F3 */ 848 + } 849 + 1005 850 res = hotkey_get(&hotkey_orig_status, &hotkey_orig_mask); 1006 851 if (!res && tp_features.hotkey_mask) { 1007 852 res = add_many_to_attr_set(hotkey_dev_attributes, 1008 853 hotkey_mask_attributes, 1009 854 ARRAY_SIZE(hotkey_mask_attributes)); 1010 855 } 856 + 857 + /* Not all thinkpads have a hardware radio switch */ 858 + if (!res && acpi_evalf(hkey_handle, &status, "WLSW", "qd")) { 859 + tp_features.hotkey_wlsw = 1; 860 + printk(IBM_INFO 861 + "radio switch found; radios are %s\n", 862 + enabled(status, 0)); 863 + res = add_to_attr_set(hotkey_dev_attributes, 864 + &dev_attr_hotkey_radio_sw.attr); 865 + } 866 + 1011 867 if (!res) 1012 868 res = register_attr_set_with_sysfs( 1013 869 hotkey_dev_attributes, 1014 870 &tpacpi_pdev->dev.kobj); 1015 - 1016 871 if (res) 1017 872 return res; 873 + 874 + /* Set up key map */ 875 + 876 + hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE, 877 + GFP_KERNEL); 878 + if (!hotkey_keycode_map) { 879 + printk(IBM_ERR "failed to allocate memory for key map\n"); 880 + return -ENOMEM; 881 + } 882 + 883 + if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) { 884 + dbg_printk(TPACPI_DBG_INIT, 885 + "using Lenovo default hot key map\n"); 886 + memcpy(hotkey_keycode_map, &lenovo_keycode_map, 887 + TPACPI_HOTKEY_MAP_SIZE); 888 + } else { 889 + dbg_printk(TPACPI_DBG_INIT, 890 + "using IBM default hot key map\n"); 891 + memcpy(hotkey_keycode_map, &ibm_keycode_map, 892 + TPACPI_HOTKEY_MAP_SIZE); 893 + } 894 + 895 + #ifndef CONFIG_THINKPAD_ACPI_INPUT_ENABLED 896 + for (i = 0; i < 12; i++) 897 + hotkey_keycode_map[i] = KEY_UNKNOWN; 898 + #endif /* ! CONFIG_THINKPAD_ACPI_INPUT_ENABLED */ 899 + 900 + set_bit(EV_KEY, tpacpi_inputdev->evbit); 901 + set_bit(EV_MSC, tpacpi_inputdev->evbit); 902 + set_bit(MSC_SCAN, tpacpi_inputdev->mscbit); 903 + tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE; 904 + tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN; 905 + tpacpi_inputdev->keycode = hotkey_keycode_map; 906 + for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) { 907 + if (hotkey_keycode_map[i] != KEY_RESERVED) { 908 + set_bit(hotkey_keycode_map[i], 909 + tpacpi_inputdev->keybit); 910 + } else { 911 + if (i < sizeof(hotkey_reserved_mask)*8) 912 + hotkey_reserved_mask |= 1 << i; 913 + } 914 + } 915 + 916 + if (tp_features.hotkey_wlsw) { 917 + set_bit(EV_SW, tpacpi_inputdev->evbit); 918 + set_bit(SW_RADIO, tpacpi_inputdev->swbit); 919 + } 920 + 921 + #ifdef CONFIG_THINKPAD_ACPI_INPUT_ENABLED 922 + dbg_printk(TPACPI_DBG_INIT, 923 + "enabling hot key handling\n"); 924 + res = hotkey_set(1, (hotkey_all_mask & ~hotkey_reserved_mask) 925 + | hotkey_orig_mask); 926 + if (res) 927 + return res; 928 + #endif /* CONFIG_THINKPAD_ACPI_INPUT_ENABLED */ 1018 929 } 1019 930 1020 931 return (tp_features.hotkey)? 0 : 1; ··· 1110 875 } 1111 876 } 1112 877 878 + static void tpacpi_input_send_key(unsigned int scancode, 879 + unsigned int keycode) 880 + { 881 + if (keycode != KEY_RESERVED) { 882 + input_report_key(tpacpi_inputdev, keycode, 1); 883 + if (keycode == KEY_UNKNOWN) 884 + input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN, 885 + scancode); 886 + input_sync(tpacpi_inputdev); 887 + 888 + input_report_key(tpacpi_inputdev, keycode, 0); 889 + if (keycode == KEY_UNKNOWN) 890 + input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN, 891 + scancode); 892 + input_sync(tpacpi_inputdev); 893 + } 894 + } 895 + 896 + static void tpacpi_input_send_radiosw(void) 897 + { 898 + int wlsw; 899 + 900 + if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw)) 901 + input_report_switch(tpacpi_inputdev, 902 + SW_RADIO, !!wlsw); 903 + } 904 + 1113 905 static void hotkey_notify(struct ibm_struct *ibm, u32 event) 1114 906 { 1115 - int hkey; 907 + u32 hkey; 908 + unsigned int keycode, scancode; 909 + int sendacpi = 1; 1116 910 1117 - if (acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) 1118 - acpi_bus_generate_event(ibm->acpi->device, event, hkey); 1119 - else { 1120 - printk(IBM_ERR "unknown hotkey event %d\n", event); 911 + if (event == 0x80 && acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) { 912 + if (tpacpi_inputdev->users > 0) { 913 + switch (hkey >> 12) { 914 + case 1: 915 + /* 0x1000-0x1FFF: key presses */ 916 + scancode = hkey & 0xfff; 917 + if (scancode > 0 && scancode < 0x21) { 918 + scancode--; 919 + keycode = hotkey_keycode_map[scancode]; 920 + tpacpi_input_send_key(scancode, keycode); 921 + sendacpi = (keycode == KEY_RESERVED 922 + || keycode == KEY_UNKNOWN); 923 + } else { 924 + printk(IBM_ERR 925 + "hotkey 0x%04x out of range for keyboard map\n", 926 + hkey); 927 + } 928 + break; 929 + case 5: 930 + /* 0x5000-0x5FFF: LID */ 931 + /* we don't handle it through this path, just 932 + * eat up known LID events */ 933 + if (hkey != 0x5001 && hkey != 0x5002) { 934 + printk(IBM_ERR 935 + "unknown LID-related hotkey event: 0x%04x\n", 936 + hkey); 937 + } 938 + break; 939 + case 7: 940 + /* 0x7000-0x7FFF: misc */ 941 + if (tp_features.hotkey_wlsw && hkey == 0x7000) { 942 + tpacpi_input_send_radiosw(); 943 + sendacpi = 0; 944 + break; 945 + } 946 + /* fallthrough to default */ 947 + default: 948 + /* case 2: dock-related */ 949 + /* 0x2305 - T43 waking up due to bay lever eject while aslept */ 950 + /* case 3: ultra-bay related. maybe bay in dock? */ 951 + /* 0x3003 - T43 after wake up by bay lever eject (0x2305) */ 952 + printk(IBM_NOTICE "unhandled hotkey event 0x%04x\n", hkey); 953 + } 954 + } 955 + 956 + if (sendacpi) 957 + acpi_bus_generate_event(ibm->acpi->device, event, hkey); 958 + } else { 959 + printk(IBM_ERR "unknown hotkey notification event %d\n", event); 1121 960 acpi_bus_generate_event(ibm->acpi->device, event, 0); 1122 961 } 962 + } 963 + 964 + static void hotkey_resume(void) 965 + { 966 + tpacpi_input_send_radiosw(); 1123 967 } 1124 968 1125 969 /* 1126 970 * Call with hotkey_mutex held 1127 971 */ 1128 - static int hotkey_get(int *status, int *mask) 972 + static int hotkey_get(int *status, u32 *mask) 1129 973 { 1130 974 if (!acpi_evalf(hkey_handle, status, "DHKC", "d")) 1131 975 return -EIO; ··· 1219 905 /* 1220 906 * Call with hotkey_mutex held 1221 907 */ 1222 - static int hotkey_set(int status, int mask) 908 + static int hotkey_set(int status, u32 mask) 1223 909 { 1224 910 int i; 1225 911 ··· 1240 926 /* procfs -------------------------------------------------------------- */ 1241 927 static int hotkey_read(char *p) 1242 928 { 1243 - int res, status, mask; 929 + int res, status; 930 + u32 mask; 1244 931 int len = 0; 1245 932 1246 933 if (!tp_features.hotkey) { ··· 1259 944 1260 945 len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0)); 1261 946 if (tp_features.hotkey_mask) { 1262 - len += sprintf(p + len, "mask:\t\t0x%04x\n", mask); 947 + len += sprintf(p + len, "mask:\t\t0x%08x\n", mask); 1263 948 len += sprintf(p + len, 1264 949 "commands:\tenable, disable, reset, <mask>\n"); 1265 950 } else { ··· 1272 957 1273 958 static int hotkey_write(char *buf) 1274 959 { 1275 - int res, status, mask; 960 + int res, status; 961 + u32 mask; 1276 962 char *cmd; 1277 963 int do_cmd = 0; 1278 964 ··· 1328 1012 .read = hotkey_read, 1329 1013 .write = hotkey_write, 1330 1014 .exit = hotkey_exit, 1015 + .resume = hotkey_resume, 1331 1016 .acpi = &ibm_hotkey_acpidriver, 1332 1017 }; 1333 1018 ··· 2087 1770 .type = ACPI_SYSTEM_NOTIFY, 2088 1771 }, 2089 1772 { 2090 - .hid = IBM_PCI_HID, 1773 + /* THIS ONE MUST NEVER BE USED FOR DRIVER AUTOLOADING. 1774 + * We just use it to get notifications of dock hotplug 1775 + * in very old thinkpads */ 1776 + .hid = PCI_ROOT_HID_STRING, 2091 1777 .notify = dock_notify, 2092 1778 .handle = &pci_handle, 2093 1779 .type = ACPI_SYSTEM_NOTIFY, ··· 2149 1829 static void dock_notify(struct ibm_struct *ibm, u32 event) 2150 1830 { 2151 1831 int docked = dock_docked(); 2152 - int pci = ibm->acpi->hid && strstr(ibm->acpi->hid, IBM_PCI_HID); 1832 + int pci = ibm->acpi->hid && strstr(ibm->acpi->hid, PCI_ROOT_HID_STRING); 2153 1833 2154 1834 if (event == 1 && !pci) /* 570 */ 2155 1835 acpi_bus_generate_event(ibm->acpi->device, event, 1); /* button */ ··· 2709 2389 2710 2390 acpi_tmp7 = acpi_evalf(ec_handle, NULL, "TMP7", "qv"); 2711 2391 2712 - if (ibm_thinkpad_ec_found && experimental) { 2392 + if (thinkpad_id.ec_model) { 2713 2393 /* 2714 2394 * Direct EC access mode: sensors at registers 2715 2395 * 0x78-0x7F, 0xC0-0xC7. Registers return 0x00 for ··· 2853 2533 snprintf(tmpi, sizeof(tmpi), "TMP%c", '0' + idx); 2854 2534 if (!acpi_evalf(ec_handle, &t, tmpi, "d")) 2855 2535 return -EIO; 2536 + if (t > 127 || t < -127) 2537 + t = TP_EC_THERMAL_TMP_NA; 2856 2538 *value = t * 1000; 2857 2539 return 0; 2858 2540 } ··· 2993 2671 * Backlight/brightness subdriver 2994 2672 */ 2995 2673 2996 - static struct backlight_device *ibm_backlight_device = NULL; 2674 + static struct backlight_device *ibm_backlight_device; 2997 2675 2998 2676 static struct backlight_ops ibm_backlight_data = { 2999 2677 .get_brightness = brightness_get, 3000 2678 .update_status = brightness_update_status, 3001 2679 }; 2680 + 2681 + static struct mutex brightness_mutex; 3002 2682 3003 2683 static int __init brightness_init(struct ibm_init_struct *iibm) 3004 2684 { ··· 3008 2684 3009 2685 vdbg_printk(TPACPI_DBG_INIT, "initializing brightness subdriver\n"); 3010 2686 2687 + mutex_init(&brightness_mutex); 2688 + 2689 + if (!brightness_mode) { 2690 + if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) 2691 + brightness_mode = 2; 2692 + else 2693 + brightness_mode = 3; 2694 + 2695 + dbg_printk(TPACPI_DBG_INIT, "selected brightness_mode=%d\n", 2696 + brightness_mode); 2697 + } 2698 + 2699 + if (brightness_mode > 3) 2700 + return -EINVAL; 2701 + 3011 2702 b = brightness_get(NULL); 3012 2703 if (b < 0) 3013 - return b; 2704 + return 1; 3014 2705 3015 2706 ibm_backlight_device = backlight_device_register( 3016 2707 TPACPI_BACKLIGHT_DEV_NAME, NULL, NULL, ··· 3061 2722 bd->props.brightness : 0); 3062 2723 } 3063 2724 2725 + /* 2726 + * ThinkPads can read brightness from two places: EC 0x31, or 2727 + * CMOS NVRAM byte 0x5E, bits 0-3. 2728 + */ 3064 2729 static int brightness_get(struct backlight_device *bd) 3065 2730 { 3066 - u8 level; 3067 - if (!acpi_ec_read(brightness_offset, &level)) 3068 - return -EIO; 2731 + u8 lec = 0, lcmos = 0, level = 0; 3069 2732 3070 - level &= 0x7; 2733 + if (brightness_mode & 1) { 2734 + if (!acpi_ec_read(brightness_offset, &lec)) 2735 + return -EIO; 2736 + lec &= 7; 2737 + level = lec; 2738 + }; 2739 + if (brightness_mode & 2) { 2740 + lcmos = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS) 2741 + & TP_NVRAM_MASK_LEVEL_BRIGHTNESS) 2742 + >> TP_NVRAM_POS_LEVEL_BRIGHTNESS; 2743 + level = lcmos; 2744 + } 2745 + 2746 + if (brightness_mode == 3 && lec != lcmos) { 2747 + printk(IBM_ERR 2748 + "CMOS NVRAM (%u) and EC (%u) do not agree " 2749 + "on display brightness level\n", 2750 + (unsigned int) lcmos, 2751 + (unsigned int) lec); 2752 + return -EIO; 2753 + } 3071 2754 3072 2755 return level; 3073 2756 } 3074 2757 3075 2758 static int brightness_set(int value) 3076 2759 { 3077 - int cmos_cmd, inc, i; 3078 - int current_value = brightness_get(NULL); 2760 + int cmos_cmd, inc, i, res; 2761 + int current_value; 3079 2762 3080 - value &= 7; 2763 + if (value > 7) 2764 + return -EINVAL; 3081 2765 3082 - cmos_cmd = value > current_value ? TP_CMOS_BRIGHTNESS_UP : TP_CMOS_BRIGHTNESS_DOWN; 3083 - inc = value > current_value ? 1 : -1; 3084 - for (i = current_value; i != value; i += inc) { 3085 - if (issue_thinkpad_cmos_command(cmos_cmd)) 3086 - return -EIO; 3087 - if (!acpi_ec_write(brightness_offset, i + inc)) 3088 - return -EIO; 2766 + res = mutex_lock_interruptible(&brightness_mutex); 2767 + if (res < 0) 2768 + return res; 2769 + 2770 + current_value = brightness_get(NULL); 2771 + if (current_value < 0) { 2772 + res = current_value; 2773 + goto errout; 3089 2774 } 3090 2775 3091 - return 0; 2776 + cmos_cmd = value > current_value ? 2777 + TP_CMOS_BRIGHTNESS_UP : 2778 + TP_CMOS_BRIGHTNESS_DOWN; 2779 + inc = value > current_value ? 1 : -1; 2780 + 2781 + res = 0; 2782 + for (i = current_value; i != value; i += inc) { 2783 + if ((brightness_mode & 2) && 2784 + issue_thinkpad_cmos_command(cmos_cmd)) { 2785 + res = -EIO; 2786 + goto errout; 2787 + } 2788 + if ((brightness_mode & 1) && 2789 + !acpi_ec_write(brightness_offset, i + inc)) { 2790 + res = -EIO; 2791 + goto errout;; 2792 + } 2793 + } 2794 + 2795 + errout: 2796 + mutex_unlock(&brightness_mutex); 2797 + return res; 3092 2798 } 3093 2799 3094 2800 static int brightness_read(char *p) ··· 3657 3273 * Enable for TP-1Y (T43), TP-78 (R51e), 3658 3274 * TP-76 (R52), TP-70 (T43, R52), which are known 3659 3275 * to be buggy. */ 3660 - if (fan_control_initial_status == 0x07 && 3661 - ibm_thinkpad_ec_found && 3662 - ((ibm_thinkpad_ec_found[0] == '1' && 3663 - ibm_thinkpad_ec_found[1] == 'Y') || 3664 - (ibm_thinkpad_ec_found[0] == '7' && 3665 - (ibm_thinkpad_ec_found[1] == '6' || 3666 - ibm_thinkpad_ec_found[1] == '8' || 3667 - ibm_thinkpad_ec_found[1] == '0')) 3668 - )) { 3669 - printk(IBM_NOTICE 3670 - "fan_init: initial fan status is " 3671 - "unknown, assuming it is in auto " 3672 - "mode\n"); 3673 - tp_features.fan_ctrl_status_undef = 1; 3276 + if (fan_control_initial_status == 0x07) { 3277 + switch (thinkpad_id.ec_model) { 3278 + case 0x5931: /* TP-1Y */ 3279 + case 0x3837: /* TP-78 */ 3280 + case 0x3637: /* TP-76 */ 3281 + case 0x3037: /* TP-70 */ 3282 + printk(IBM_NOTICE 3283 + "fan_init: initial fan status is " 3284 + "unknown, assuming it is in auto " 3285 + "mode\n"); 3286 + tp_features.fan_ctrl_status_undef = 1; 3287 + ;; 3288 + } 3674 3289 } 3675 3290 } else { 3676 3291 printk(IBM_ERR ··· 3857 3474 3858 3475 static void fan_watchdog_reset(void) 3859 3476 { 3860 - static int fan_watchdog_active = 0; 3477 + static int fan_watchdog_active; 3861 3478 3862 3479 if (fan_control_access_mode == TPACPI_FAN_WR_NONE) 3863 3480 return; ··· 4260 3877 ****************************************************************************/ 4261 3878 4262 3879 /* /proc support */ 4263 - static struct proc_dir_entry *proc_dir = NULL; 3880 + static struct proc_dir_entry *proc_dir; 4264 3881 4265 3882 /* Subdriver registry */ 4266 3883 static LIST_HEAD(tpacpi_all_drivers); ··· 4403 4020 4404 4021 /* Probing */ 4405 4022 4406 - static char *ibm_thinkpad_ec_found = NULL; 4407 - 4408 - static char* __init check_dmi_for_ec(void) 4023 + static void __init get_thinkpad_model_data(struct thinkpad_id_data *tp) 4409 4024 { 4410 4025 struct dmi_device *dev = NULL; 4411 4026 char ec_fw_string[18]; 4027 + 4028 + if (!tp) 4029 + return; 4030 + 4031 + memset(tp, 0, sizeof(*tp)); 4032 + 4033 + if (dmi_name_in_vendors("IBM")) 4034 + tp->vendor = PCI_VENDOR_ID_IBM; 4035 + else if (dmi_name_in_vendors("LENOVO")) 4036 + tp->vendor = PCI_VENDOR_ID_LENOVO; 4037 + else 4038 + return; 4039 + 4040 + tp->bios_version_str = kstrdup(dmi_get_system_info(DMI_BIOS_VERSION), 4041 + GFP_KERNEL); 4042 + if (!tp->bios_version_str) 4043 + return; 4044 + tp->bios_model = tp->bios_version_str[0] 4045 + | (tp->bios_version_str[1] << 8); 4412 4046 4413 4047 /* 4414 4048 * ThinkPad T23 or newer, A31 or newer, R50e or newer, ··· 4440 4040 ec_fw_string) == 1) { 4441 4041 ec_fw_string[sizeof(ec_fw_string) - 1] = 0; 4442 4042 ec_fw_string[strcspn(ec_fw_string, " ]")] = 0; 4443 - return kstrdup(ec_fw_string, GFP_KERNEL); 4043 + 4044 + tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL); 4045 + tp->ec_model = ec_fw_string[0] 4046 + | (ec_fw_string[1] << 8); 4047 + break; 4444 4048 } 4445 4049 } 4446 - return NULL; 4050 + 4051 + tp->model_str = kstrdup(dmi_get_system_info(DMI_PRODUCT_VERSION), 4052 + GFP_KERNEL); 4053 + if (strnicmp(tp->model_str, "ThinkPad", 8) != 0) { 4054 + kfree(tp->model_str); 4055 + tp->model_str = NULL; 4056 + } 4447 4057 } 4448 4058 4449 4059 static int __init probe_for_thinkpad(void) ··· 4467 4057 * Non-ancient models have better DMI tagging, but very old models 4468 4058 * don't. 4469 4059 */ 4470 - is_thinkpad = dmi_name_in_vendors("ThinkPad"); 4060 + is_thinkpad = (thinkpad_id.model_str != NULL); 4471 4061 4472 4062 /* ec is required because many other handles are relative to it */ 4473 4063 IBM_ACPIHANDLE_INIT(ec); ··· 4483 4073 * false positives a damn great deal 4484 4074 */ 4485 4075 if (!is_thinkpad) 4486 - is_thinkpad = dmi_name_in_vendors("IBM"); 4076 + is_thinkpad = (thinkpad_id.vendor == PCI_VENDOR_ID_IBM); 4487 4077 4488 4078 if (!is_thinkpad && !force_load) 4489 4079 return -ENODEV; ··· 4595 4185 module_param_named(debug, dbg_level, uint, 0); 4596 4186 4597 4187 static int force_load; 4598 - module_param(force_load, int, 0); 4188 + module_param(force_load, bool, 0); 4599 4189 4600 4190 static int fan_control_allowed; 4601 - module_param_named(fan_control, fan_control_allowed, int, 0); 4191 + module_param_named(fan_control, fan_control_allowed, bool, 0); 4192 + 4193 + static int brightness_mode; 4194 + module_param_named(brightness_mode, brightness_mode, int, 0); 4602 4195 4603 4196 #define IBM_PARAM(feature) \ 4604 4197 module_param_call(feature, set_ibm_param, NULL, NULL, 0) ··· 4629 4216 int ret, i; 4630 4217 4631 4218 /* Driver-level probe */ 4219 + 4220 + get_thinkpad_model_data(&thinkpad_id); 4632 4221 ret = probe_for_thinkpad(); 4633 - if (ret) 4222 + if (ret) { 4223 + thinkpad_acpi_module_exit(); 4634 4224 return ret; 4225 + } 4635 4226 4636 4227 /* Driver initialization */ 4637 - ibm_thinkpad_ec_found = check_dmi_for_ec(); 4228 + 4638 4229 IBM_ACPIHANDLE_INIT(ecrd); 4639 4230 IBM_ACPIHANDLE_INIT(ecwr); 4640 4231 ··· 4682 4265 thinkpad_acpi_module_exit(); 4683 4266 return ret; 4684 4267 } 4268 + tpacpi_inputdev = input_allocate_device(); 4269 + if (!tpacpi_inputdev) { 4270 + printk(IBM_ERR "unable to allocate input device\n"); 4271 + thinkpad_acpi_module_exit(); 4272 + return -ENOMEM; 4273 + } else { 4274 + /* Prepare input device, but don't register */ 4275 + tpacpi_inputdev->name = "ThinkPad Extra Buttons"; 4276 + tpacpi_inputdev->phys = IBM_DRVR_NAME "/input0"; 4277 + tpacpi_inputdev->id.bustype = BUS_HOST; 4278 + tpacpi_inputdev->id.vendor = (thinkpad_id.vendor) ? 4279 + thinkpad_id.vendor : 4280 + PCI_VENDOR_ID_IBM; 4281 + tpacpi_inputdev->id.product = TPACPI_HKEY_INPUT_PRODUCT; 4282 + tpacpi_inputdev->id.version = TPACPI_HKEY_INPUT_VERSION; 4283 + } 4685 4284 for (i = 0; i < ARRAY_SIZE(ibms_init); i++) { 4686 4285 ret = ibm_init(&ibms_init[i]); 4687 4286 if (ret >= 0 && *ibms_init[i].param) ··· 4706 4273 thinkpad_acpi_module_exit(); 4707 4274 return ret; 4708 4275 } 4276 + } 4277 + ret = input_register_device(tpacpi_inputdev); 4278 + if (ret < 0) { 4279 + printk(IBM_ERR "unable to register input device\n"); 4280 + thinkpad_acpi_module_exit(); 4281 + return ret; 4282 + } else { 4283 + tp_features.input_device_registered = 1; 4709 4284 } 4710 4285 4711 4286 return 0; ··· 4731 4290 4732 4291 dbg_printk(TPACPI_DBG_INIT, "finished subdriver exit path...\n"); 4733 4292 4293 + if (tpacpi_inputdev) { 4294 + if (tp_features.input_device_registered) 4295 + input_unregister_device(tpacpi_inputdev); 4296 + else 4297 + input_free_device(tpacpi_inputdev); 4298 + } 4299 + 4734 4300 if (tpacpi_hwmon) 4735 4301 hwmon_device_unregister(tpacpi_hwmon); 4736 4302 ··· 4750 4302 if (proc_dir) 4751 4303 remove_proc_entry(IBM_PROC_DIR, acpi_root_dir); 4752 4304 4753 - kfree(ibm_thinkpad_ec_found); 4305 + kfree(thinkpad_id.bios_version_str); 4306 + kfree(thinkpad_id.ec_version_str); 4307 + kfree(thinkpad_id.model_str); 4754 4308 } 4755 4309 4756 4310 module_init(thinkpad_acpi_module_init);
+36 -6
drivers/misc/thinkpad_acpi.h
··· 32 32 #include <linux/list.h> 33 33 #include <linux/mutex.h> 34 34 35 + #include <linux/nvram.h> 35 36 #include <linux/proc_fs.h> 36 37 #include <linux/sysfs.h> 37 38 #include <linux/backlight.h> ··· 40 39 #include <linux/platform_device.h> 41 40 #include <linux/hwmon.h> 42 41 #include <linux/hwmon-sysfs.h> 42 + #include <linux/input.h> 43 43 #include <asm/uaccess.h> 44 44 45 45 #include <linux/dmi.h> ··· 50 48 #include <acpi/acpi_drivers.h> 51 49 #include <acpi/acnamesp.h> 52 50 51 + #include <linux/pci_ids.h> 53 52 54 53 /**************************************************************************** 55 54 * Main driver ··· 81 78 #define TP_CMOS_BRIGHTNESS_UP 4 82 79 #define TP_CMOS_BRIGHTNESS_DOWN 5 83 80 81 + /* ThinkPad CMOS NVRAM constants */ 82 + #define TP_NVRAM_ADDR_BRIGHTNESS 0x5e 83 + #define TP_NVRAM_MASK_LEVEL_BRIGHTNESS 0x07 84 + #define TP_NVRAM_POS_LEVEL_BRIGHTNESS 0 85 + 84 86 #define onoff(status,bit) ((status) & (1 << (bit)) ? "on" : "off") 85 87 #define enabled(status,bit) ((status) & (1 << (bit)) ? "enabled" : "disabled") 86 88 #define strlencmp(a,b) (strncmp((a), (b), strlen(b))) ··· 106 98 #define vdbg_printk(a_dbg_level, format, arg...) 107 99 #endif 108 100 101 + /* Input IDs */ 102 + #define TPACPI_HKEY_INPUT_VENDOR PCI_VENDOR_ID_IBM 103 + #define TPACPI_HKEY_INPUT_PRODUCT 0x5054 /* "TP" */ 104 + #define TPACPI_HKEY_INPUT_VERSION 0x4101 105 + 109 106 /* ACPI HIDs */ 110 107 #define IBM_HKEY_HID "IBM0068" 111 - #define IBM_PCI_HID "PNP0A03" 112 108 113 109 /* ACPI helpers */ 114 110 static int __must_check acpi_evalf(acpi_handle handle, ··· 173 161 static struct platform_device *tpacpi_pdev; 174 162 static struct class_device *tpacpi_hwmon; 175 163 static struct platform_driver tpacpi_pdriver; 164 + static struct input_dev *tpacpi_inputdev; 176 165 static int tpacpi_create_driver_attributes(struct device_driver *drv); 177 166 static void tpacpi_remove_driver_attributes(struct device_driver *drv); 178 167 ··· 181 168 static int experimental; 182 169 static u32 dbg_level; 183 170 static int force_load; 184 - static char *ibm_thinkpad_ec_found; 185 171 186 - static char* check_dmi_for_ec(void); 187 172 static int thinkpad_acpi_module_init(void); 188 173 static void thinkpad_acpi_module_exit(void); 189 174 ··· 208 197 int (*read) (char *); 209 198 int (*write) (char *); 210 199 void (*exit) (void); 200 + void (*resume) (void); 211 201 212 202 struct list_head all_drivers; 213 203 ··· 240 228 u16 bluetooth:1; 241 229 u16 hotkey:1; 242 230 u16 hotkey_mask:1; 231 + u16 hotkey_wlsw:1; 243 232 u16 light:1; 244 233 u16 light_status:1; 245 234 u16 wan:1; 246 235 u16 fan_ctrl_status_undef:1; 236 + u16 input_device_registered:1; 247 237 } tp_features; 238 + 239 + struct thinkpad_id_data { 240 + unsigned int vendor; /* ThinkPad vendor: 241 + * PCI_VENDOR_ID_IBM/PCI_VENDOR_ID_LENOVO */ 242 + 243 + char *bios_version_str; /* Something like 1ZET51WW (1.03z) */ 244 + char *ec_version_str; /* Something like 1ZHT51WW-1.04a */ 245 + 246 + u16 bios_model; /* Big Endian, TP-1Y = 0x5931, 0 = unknown */ 247 + u16 ec_model; 248 + 249 + char *model_str; 250 + }; 251 + 252 + static struct thinkpad_id_data thinkpad_id; 248 253 249 254 static struct list_head tpacpi_all_drivers; 250 255 ··· 329 300 330 301 static struct backlight_device *ibm_backlight_device; 331 302 static int brightness_offset = 0x31; 303 + static int brightness_mode; 332 304 333 305 static int brightness_init(struct ibm_init_struct *iibm); 334 306 static void brightness_exit(void); ··· 445 415 */ 446 416 447 417 static int hotkey_orig_status; 448 - static int hotkey_orig_mask; 418 + static u32 hotkey_orig_mask; 449 419 450 420 static struct mutex hotkey_mutex; 451 421 452 422 static int hotkey_init(struct ibm_init_struct *iibm); 453 423 static void hotkey_exit(void); 454 - static int hotkey_get(int *status, int *mask); 455 - static int hotkey_set(int status, int mask); 424 + static int hotkey_get(int *status, u32 *mask); 425 + static int hotkey_set(int status, u32 mask); 456 426 static void hotkey_notify(struct ibm_struct *ibm, u32 event); 457 427 static int hotkey_read(char *p); 458 428 static int hotkey_write(char *buf);
+7
drivers/video/Kconfig
··· 12 12 tristate 13 13 default n 14 14 15 + config VIDEO_OUTPUT_CONTROL 16 + tristate "Lowlevel video output switch controls" 17 + default m 18 + help 19 + This framework adds support for low-level control of the video 20 + output switch. 21 + 15 22 config FB 16 23 tristate "Support for frame buffer devices" 17 24 ---help---
+3
drivers/video/Makefile
··· 123 123 124 124 # the test framebuffer is last 125 125 obj-$(CONFIG_FB_VIRTUAL) += vfb.o 126 + 127 + #video output switch sysfs driver 128 + obj-$(CONFIG_VIDEO_OUTPUT_CONTROL) += output.o
+43 -20
include/acpi/acmacros.h
··· 486 486 #define ACPI_FUNCTION_NAME(name) 487 487 #endif 488 488 489 + #ifdef DEBUG_FUNC_TRACE 490 + 489 491 #define ACPI_FUNCTION_TRACE(a) ACPI_FUNCTION_NAME(a) \ 490 492 acpi_ut_trace(ACPI_DEBUG_PARAMETERS) 491 493 #define ACPI_FUNCTION_TRACE_PTR(a,b) ACPI_FUNCTION_NAME(a) \ ··· 565 563 566 564 #endif /* ACPI_SIMPLE_RETURN_MACROS */ 567 565 566 + #else /* !DEBUG_FUNC_TRACE */ 567 + 568 + #define ACPI_FUNCTION_TRACE(a) 569 + #define ACPI_FUNCTION_TRACE_PTR(a,b) 570 + #define ACPI_FUNCTION_TRACE_U32(a,b) 571 + #define ACPI_FUNCTION_TRACE_STR(a,b) 572 + #define ACPI_FUNCTION_EXIT 573 + #define ACPI_FUNCTION_STATUS_EXIT(s) 574 + #define ACPI_FUNCTION_VALUE_EXIT(s) 575 + #define ACPI_FUNCTION_TRACE(a) 576 + #define ACPI_FUNCTION_ENTRY() 577 + 578 + #define return_VOID return 579 + #define return_ACPI_STATUS(s) return(s) 580 + #define return_VALUE(s) return(s) 581 + #define return_UINT8(s) return(s) 582 + #define return_UINT32(s) return(s) 583 + #define return_PTR(s) return(s) 584 + 585 + #endif /* DEBUG_FUNC_TRACE */ 586 + 568 587 /* Conditional execution */ 569 588 570 589 #define ACPI_DEBUG_EXEC(a) a ··· 622 599 #define ACPI_DEBUG_EXEC(a) 623 600 #define ACPI_NORMAL_EXEC(a) a; 624 601 625 - #define ACPI_DEBUG_DEFINE(a) 626 - #define ACPI_DEBUG_ONLY_MEMBERS(a) 627 - #define ACPI_FUNCTION_NAME(a) 628 - #define ACPI_FUNCTION_TRACE(a) 629 - #define ACPI_FUNCTION_TRACE_PTR(a,b) 630 - #define ACPI_FUNCTION_TRACE_U32(a,b) 631 - #define ACPI_FUNCTION_TRACE_STR(a,b) 632 - #define ACPI_FUNCTION_EXIT 633 - #define ACPI_FUNCTION_STATUS_EXIT(s) 634 - #define ACPI_FUNCTION_VALUE_EXIT(s) 635 - #define ACPI_FUNCTION_ENTRY() 636 - #define ACPI_DUMP_STACK_ENTRY(a) 637 - #define ACPI_DUMP_OPERANDS(a,b,c,d,e) 638 - #define ACPI_DUMP_ENTRY(a,b) 639 - #define ACPI_DUMP_TABLES(a,b) 640 - #define ACPI_DUMP_PATHNAME(a,b,c,d) 641 - #define ACPI_DUMP_RESOURCE_LIST(a) 642 - #define ACPI_DUMP_BUFFER(a,b) 643 - #define ACPI_DEBUG_PRINT(pl) 644 - #define ACPI_DEBUG_PRINT_RAW(pl) 602 + #define ACPI_DEBUG_DEFINE(a) do { } while(0) 603 + #define ACPI_DEBUG_ONLY_MEMBERS(a) do { } while(0) 604 + #define ACPI_FUNCTION_NAME(a) do { } while(0) 605 + #define ACPI_FUNCTION_TRACE(a) do { } while(0) 606 + #define ACPI_FUNCTION_TRACE_PTR(a,b) do { } while(0) 607 + #define ACPI_FUNCTION_TRACE_U32(a,b) do { } while(0) 608 + #define ACPI_FUNCTION_TRACE_STR(a,b) do { } while(0) 609 + #define ACPI_FUNCTION_EXIT do { } while(0) 610 + #define ACPI_FUNCTION_STATUS_EXIT(s) do { } while(0) 611 + #define ACPI_FUNCTION_VALUE_EXIT(s) do { } while(0) 612 + #define ACPI_FUNCTION_ENTRY() do { } while(0) 613 + #define ACPI_DUMP_STACK_ENTRY(a) do { } while(0) 614 + #define ACPI_DUMP_OPERANDS(a,b,c,d,e) do { } while(0) 615 + #define ACPI_DUMP_ENTRY(a,b) do { } while(0) 616 + #define ACPI_DUMP_TABLES(a,b) do { } while(0) 617 + #define ACPI_DUMP_PATHNAME(a,b,c,d) do { } while(0) 618 + #define ACPI_DUMP_RESOURCE_LIST(a) do { } while(0) 619 + #define ACPI_DUMP_BUFFER(a,b) do { } while(0) 620 + #define ACPI_DEBUG_PRINT(pl) do { } while(0) 621 + #define ACPI_DEBUG_PRINT_RAW(pl) do { } while(0) 645 622 646 623 #define return_VOID return 647 624 #define return_ACPI_STATUS(s) return(s)
+2 -2
include/acpi/acoutput.h
··· 178 178 179 179 /* Defaults for debug_level, debug and normal */ 180 180 181 - #define ACPI_DEBUG_DEFAULT (ACPI_LV_INIT | ACPI_LV_WARN | ACPI_LV_ERROR | ACPI_LV_DEBUG_OBJECT) 182 - #define ACPI_NORMAL_DEFAULT (ACPI_LV_INIT | ACPI_LV_WARN | ACPI_LV_ERROR | ACPI_LV_DEBUG_OBJECT) 181 + #define ACPI_DEBUG_DEFAULT (ACPI_LV_INIT | ACPI_LV_WARN | ACPI_LV_ERROR) 182 + #define ACPI_NORMAL_DEFAULT (ACPI_LV_INIT | ACPI_LV_WARN | ACPI_LV_ERROR) 183 183 #define ACPI_DEBUG_ALL (ACPI_LV_AML_DISASSEMBLE | ACPI_LV_ALL_EXCEPTIONS | ACPI_LV_ALL) 184 184 185 185 #endif /* __ACOUTPUT_H__ */
+2 -1
include/acpi/acpi_bus.h
··· 321 321 }; 322 322 323 323 extern struct kset acpi_subsys; 324 - 324 + extern int acpi_bus_generate_genetlink_event(struct acpi_device *device, 325 + u8 type, int data); 325 326 /* 326 327 * External Functions 327 328 */
+1 -1
include/acpi/platform/acenv.h
··· 136 136 137 137 /*! [Begin] no source code translation */ 138 138 139 - #if defined(__linux__) 139 + #if defined(_LINUX) || defined(__linux__) 140 140 #include "aclinux.h" 141 141 142 142 #elif defined(_AED_EFI)
+3
include/acpi/platform/aclinux.h
··· 91 91 #define ACPI_USE_NATIVE_DIVIDE 92 92 #endif 93 93 94 + #ifndef __cdecl 94 95 #define __cdecl 96 + #endif 97 + 95 98 #define ACPI_FLUSH_CPU_CACHE() 96 99 #endif /* __KERNEL__ */ 97 100
+44 -3
include/acpi/processor.h
··· 21 21 #define ACPI_PSD_REV0_REVISION 0 /* Support for _PSD as in ACPI 3.0 */ 22 22 #define ACPI_PSD_REV0_ENTRIES 5 23 23 24 + #define ACPI_TSD_REV0_REVISION 0 /* Support for _PSD as in ACPI 3.0 */ 25 + #define ACPI_TSD_REV0_ENTRIES 5 24 26 /* 25 27 * Types of coordination defined in ACPI 3.0. Same macros can be used across 26 28 * P, C and T states ··· 127 125 128 126 /* Throttling Control */ 129 127 128 + struct acpi_tsd_package { 129 + acpi_integer num_entries; 130 + acpi_integer revision; 131 + acpi_integer domain; 132 + acpi_integer coord_type; 133 + acpi_integer num_processors; 134 + } __attribute__ ((packed)); 135 + 136 + struct acpi_ptc_register { 137 + u8 descriptor; 138 + u16 length; 139 + u8 space_id; 140 + u8 bit_width; 141 + u8 bit_offset; 142 + u8 reserved; 143 + u64 address; 144 + } __attribute__ ((packed)); 145 + 146 + struct acpi_processor_tx_tss { 147 + acpi_integer freqpercentage; /* */ 148 + acpi_integer power; /* milliWatts */ 149 + acpi_integer transition_latency; /* microseconds */ 150 + acpi_integer control; /* control value */ 151 + acpi_integer status; /* success indicator */ 152 + }; 130 153 struct acpi_processor_tx { 131 154 u16 power; 132 155 u16 performance; 133 156 }; 134 157 158 + struct acpi_processor; 135 159 struct acpi_processor_throttling { 136 - int state; 160 + unsigned int state; 161 + unsigned int platform_limit; 162 + struct acpi_pct_register control_register; 163 + struct acpi_pct_register status_register; 164 + unsigned int state_count; 165 + struct acpi_processor_tx_tss *states_tss; 166 + struct acpi_tsd_package domain_info; 167 + cpumask_t shared_cpu_map; 168 + int (*acpi_processor_get_throttling) (struct acpi_processor * pr); 169 + int (*acpi_processor_set_throttling) (struct acpi_processor * pr, 170 + int state); 171 + 137 172 u32 address; 138 173 u8 duty_offset; 139 174 u8 duty_width; 140 - int state_count; 141 175 struct acpi_processor_tx states[ACPI_PROCESSOR_MAX_THROTTLING]; 142 176 }; 143 177 ··· 207 169 u32 id; 208 170 u32 pblk; 209 171 int performance_platform_limit; 172 + int throttling_platform_limit; 173 + /* 0 - states 0..n-th state available */ 174 + 210 175 struct acpi_processor_flags flags; 211 176 struct acpi_processor_power power; 212 177 struct acpi_processor_performance *performance; ··· 311 270 312 271 /* in processor_throttling.c */ 313 272 int acpi_processor_get_throttling_info(struct acpi_processor *pr); 314 - int acpi_processor_set_throttling(struct acpi_processor *pr, int state); 273 + extern int acpi_processor_set_throttling(struct acpi_processor *pr, int state); 315 274 extern struct file_operations acpi_processor_throttling_fops; 316 275 317 276 /* in processor_idle.c */
+2
include/linux/pci_ids.h
··· 2040 2040 #define PCI_DEVICE_ID_ALTIMA_AC9100 0x03ea 2041 2041 #define PCI_DEVICE_ID_ALTIMA_AC1003 0x03eb 2042 2042 2043 + #define PCI_VENDOR_ID_LENOVO 0x17aa 2044 + 2043 2045 #define PCI_VENDOR_ID_ARECA 0x17d3 2044 2046 #define PCI_DEVICE_ID_ARECA_1110 0x1110 2045 2047 #define PCI_DEVICE_ID_ARECA_1120 0x1120