diff options
120 files changed, 3235 insertions, 1165 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index a5cb7839a679..c175eedadb5f 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt | |||
| @@ -180,24 +180,11 @@ Who: Adrian Bunk <bunk@stusta.de> | |||
| 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 | What: ACPI procfs interface | 183 | What: ACPI procfs interface |
| 198 | When: July 2007 | 184 | When: July 2008 |
| 199 | Why: After ACPI sysfs conversion, ACPI attributes will be duplicated | 185 | Why: ACPI sysfs conversion should be finished by January 2008. |
| 200 | in sysfs and the ACPI procfs interface should be removed. | 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 | Who: Zhang Rui <rui.zhang@intel.com> | 188 | Who: Zhang Rui <rui.zhang@intel.com> |
| 202 | 189 | ||
| 203 | --------------------------- | 190 | --------------------------- |
diff --git a/Documentation/thinkpad-acpi.txt b/Documentation/thinkpad-acpi.txt index 9e6b94face4b..6711fbcf4080 100644 --- a/Documentation/thinkpad-acpi.txt +++ b/Documentation/thinkpad-acpi.txt | |||
| @@ -1,11 +1,11 @@ | |||
| 1 | ThinkPad ACPI Extras Driver | 1 | ThinkPad ACPI Extras Driver |
| 2 | 2 | ||
| 3 | Version 0.14 | 3 | Version 0.15 |
| 4 | April 21st, 2007 | 4 | July 1st, 2007 |
| 5 | 5 | ||
| 6 | Borislav Deianov <borislav@users.sf.net> | 6 | Borislav Deianov <borislav@users.sf.net> |
| 7 | Henrique de Moraes Holschuh <hmh@hmh.eng.br> | 7 | Henrique de Moraes Holschuh <hmh@hmh.eng.br> |
| 8 | http://ibm-acpi.sf.net/ | 8 | http://ibm-acpi.sf.net/ |
| 9 | 9 | ||
| 10 | 10 | ||
| 11 | This is a Linux driver for the IBM and Lenovo ThinkPad laptops. It | 11 | This is a Linux driver for the IBM and Lenovo ThinkPad laptops. It |
| @@ -134,54 +134,68 @@ end of this document. Changes to the sysfs interface done by the kernel | |||
| 134 | subsystems are not documented here, nor are they tracked by this | 134 | subsystems are not documented here, nor are they tracked by this |
| 135 | attribute. | 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 | Hot keys | 152 | Hot keys |
| 138 | -------- | 153 | -------- |
| 139 | 154 | ||
| 140 | procfs: /proc/acpi/ibm/hotkey | 155 | procfs: /proc/acpi/ibm/hotkey |
| 141 | sysfs device attribute: hotkey_* | 156 | sysfs device attribute: hotkey_* |
| 142 | 157 | ||
| 143 | Without this driver, only the Fn-F4 key (sleep button) generates an | 158 | In a ThinkPad, the ACPI HKEY handler is responsible for comunicating |
| 144 | ACPI event. With the driver loaded, the hotkey feature enabled and the | 159 | some important events and also keyboard hot key presses to the operating |
| 145 | mask set (see below), the various hot keys generate ACPI events in the | 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 | following format: | 166 | following format: |
| 147 | 167 | ||
| 148 | ibm/hotkey HKEY 00000080 0000xxxx | 168 | ibm/hotkey HKEY 00000080 0000xxxx |
| 149 | 169 | ||
| 150 | The last four digits vary depending on the key combination pressed. | 170 | or events over the input layer. The input layer support accepts the |
| 151 | All labeled Fn-Fx key combinations generate distinct events. In | 171 | standard IOCTLs to remap the keycodes assigned to each hotkey. |
| 152 | addition, the lid microswitch and some docking station buttons may | 172 | |
| 153 | also generate such events. | 173 | When the input device is open, the driver will suppress any ACPI hot key |
| 154 | 174 | events that get translated into a meaningful input layer event, in order | |
| 155 | The bit mask allows some control over which hot keys generate ACPI | 175 | to avoid sending duplicate events to userspace. Hot keys that are |
| 156 | events. Not all bits in the mask can be modified. Not all bits that | 176 | mapped to KEY_RESERVED in the keymap are not translated, and will always |
| 157 | can be modified do anything. Not all hot keys can be individually | 177 | generate an ACPI ibm/hotkey HKEY event, and no input layer events. |
| 158 | controlled by the mask. Most recent ThinkPad models honor the | 178 | |
| 159 | following bits (assuming the hot keys feature has been enabled): | 179 | The hot key bit mask allows some control over which hot keys generate |
| 160 | 180 | events. If a key is "masked" (bit set to 0 in the mask), the firmware | |
| 161 | key bit behavior when set behavior when unset | 181 | will handle it. If it is "unmasked", it signals the firmware that |
| 162 | 182 | thinkpad-acpi would prefer to handle it, if the firmware would be so | |
| 163 | Fn-F3 always generates ACPI event | 183 | kind to allow it (and it often doesn't!). |
| 164 | Fn-F4 always generates ACPI event | 184 | |
| 165 | Fn-F5 0010 generate ACPI event enable/disable Bluetooth | 185 | Not all bits in the mask can be modified. Not all bits that can be |
| 166 | Fn-F7 0040 generate ACPI event switch LCD and external display | 186 | modified do anything. Not all hot keys can be individually controlled |
| 167 | Fn-F8 0080 generate ACPI event expand screen or none | 187 | by the mask. Some models do not support the mask at all, and in those |
| 168 | Fn-F9 0100 generate ACPI event none | 188 | models, hot keys cannot be controlled individually. The behaviour of |
| 169 | Fn-F12 always generates ACPI event | 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 | 191 | Note that unmasking some keys prevents their default behavior. For |
| 172 | not support Fn-F5 and Fn-F9. Other models do not support the mask at | 192 | example, if Fn+F5 is unmasked, that key will no longer enable/disable |
| 173 | all. On those models, hot keys cannot be controlled individually. | 193 | Bluetooth by itself. |
| 174 | 194 | ||
| 175 | Note that enabling ACPI events for some keys prevents their default | 195 | Note also that not all Fn key combinations are supported through ACPI. |
| 176 | behavior. For example, if events for Fn-F5 are enabled, that key will | 196 | For example, on the X40, the brightness, volume and "Access IBM" buttons |
| 177 | no longer enable/disable Bluetooth by itself. This can still be done | 197 | do not generate ACPI events even with this driver. They *can* be used |
| 178 | from an acpid handler for the ibm/hotkey event. | 198 | through the "ThinkPad Buttons" utility, see http://www.nongnu.org/tpb/ |
| 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/ | ||
| 185 | 199 | ||
| 186 | procfs notes: | 200 | procfs notes: |
| 187 | 201 | ||
| @@ -189,9 +203,9 @@ The following commands can be written to the /proc/acpi/ibm/hotkey file: | |||
| 189 | 203 | ||
| 190 | echo enable > /proc/acpi/ibm/hotkey -- enable the hot keys feature | 204 | echo enable > /proc/acpi/ibm/hotkey -- enable the hot keys feature |
| 191 | echo disable > /proc/acpi/ibm/hotkey -- disable the hot keys feature | 205 | echo disable > /proc/acpi/ibm/hotkey -- disable the hot keys feature |
| 192 | echo 0xffff > /proc/acpi/ibm/hotkey -- enable all possible hot keys | 206 | echo 0xffffffff > /proc/acpi/ibm/hotkey -- enable all hot keys |
| 193 | echo 0x0000 > /proc/acpi/ibm/hotkey -- disable all possible hot keys | 207 | echo 0 > /proc/acpi/ibm/hotkey -- disable all possible hot keys |
| 194 | ... any other 4-hex-digit mask ... | 208 | ... any other 8-hex-digit mask ... |
| 195 | echo reset > /proc/acpi/ibm/hotkey -- restore the original mask | 209 | echo reset > /proc/acpi/ibm/hotkey -- restore the original mask |
| 196 | 210 | ||
| 197 | sysfs notes: | 211 | sysfs notes: |
| @@ -202,7 +216,7 @@ sysfs notes: | |||
| 202 | key feature status will be restored to this value. | 216 | key feature status will be restored to this value. |
| 203 | 217 | ||
| 204 | 0: hot keys were disabled | 218 | 0: hot keys were disabled |
| 205 | 1: hot keys were enabled | 219 | 1: hot keys were enabled (unusual) |
| 206 | 220 | ||
| 207 | hotkey_bios_mask: | 221 | hotkey_bios_mask: |
| 208 | Returns the hot keys mask when thinkpad-acpi was loaded. | 222 | Returns the hot keys mask when thinkpad-acpi was loaded. |
| @@ -217,9 +231,182 @@ sysfs notes: | |||
| 217 | 1: enables the hot keys feature / feature enabled | 231 | 1: enables the hot keys feature / feature enabled |
| 218 | 232 | ||
| 219 | hotkey_mask: | 233 | hotkey_mask: |
| 220 | bit mask to enable ACPI event generation for each hot | 234 | bit mask to enable driver-handling and ACPI event |
| 221 | key (see above). Returns the current status of the hot | 235 | generation for each hot key (see above). Returns the |
| 222 | keys mask, and allows one to modify it. | 236 | current status of the hot keys mask, and allows one to |
| 237 | modify it. | ||
| 238 | |||
| 239 | hotkey_all_mask: | ||
| 240 | bit mask that should enable event reporting for all | ||
| 241 | supported hot keys, when echoed to hotkey_mask above. | ||
| 242 | Unless you know which events need to be handled | ||
| 243 | passively (because the firmware *will* handle them | ||
| 244 | anyway), do *not* use hotkey_all_mask. Use | ||
| 245 | hotkey_recommended_mask, instead. You have been warned. | ||
| 246 | |||
| 247 | hotkey_recommended_mask: | ||
| 248 | bit mask that should enable event reporting for all | ||
| 249 | supported hot keys, except those which are always | ||
| 250 | handled by the firmware anyway. Echo it to | ||
| 251 | hotkey_mask above, to use. | ||
| 252 | |||
| 253 | hotkey_radio_sw: | ||
| 254 | if the ThinkPad has a hardware radio switch, this | ||
| 255 | attribute will read 0 if the switch is in the "radios | ||
| 256 | disabled" postition, and 1 if the switch is in the | ||
| 257 | "radios enabled" position. | ||
| 258 | |||
| 259 | input layer notes: | ||
| 260 | |||
| 261 | A Hot key is mapped to a single input layer EV_KEY event, possibly | ||
| 262 | followed by an EV_MSC MSC_SCAN event that shall contain that key's scan | ||
| 263 | code. An EV_SYN event will always be generated to mark the end of the | ||
| 264 | event block. | ||
| 265 | |||
| 266 | Do not use the EV_MSC MSC_SCAN events to process keys. They are to be | ||
| 267 | used as a helper to remap keys, only. They are particularly useful when | ||
| 268 | remapping KEY_UNKNOWN keys. | ||
| 269 | |||
| 270 | The events are available in an input device, with the following id: | ||
| 271 | |||
| 272 | Bus: BUS_HOST | ||
| 273 | vendor: 0x1014 (PCI_VENDOR_ID_IBM) or | ||
| 274 | 0x17aa (PCI_VENDOR_ID_LENOVO) | ||
| 275 | product: 0x5054 ("TP") | ||
| 276 | version: 0x4101 | ||
| 277 | |||
| 278 | The version will have its LSB incremented if the keymap changes in a | ||
| 279 | backwards-compatible way. The MSB shall always be 0x41 for this input | ||
| 280 | device. If the MSB is not 0x41, do not use the device as described in | ||
| 281 | this section, as it is either something else (e.g. another input device | ||
| 282 | exported by a thinkpad driver, such as HDAPS) or its functionality has | ||
| 283 | been changed in a non-backwards compatible way. | ||
| 284 | |||
| 285 | Adding other event types for other functionalities shall be considered a | ||
| 286 | backwards-compatible change for this input device. | ||
| 287 | |||
| 288 | Thinkpad-acpi Hot Key event map (version 0x4101): | ||
| 289 | |||
| 290 | ACPI Scan | ||
| 291 | event code Key Notes | ||
| 292 | |||
| 293 | 0x1001 0x00 FN+F1 - | ||
| 294 | 0x1002 0x01 FN+F2 IBM: battery (rare) | ||
| 295 | Lenovo: Screen lock | ||
| 296 | |||
| 297 | 0x1003 0x02 FN+F3 Many IBM models always report | ||
| 298 | this hot key, even with hot keys | ||
| 299 | disabled or with Fn+F3 masked | ||
| 300 | off | ||
| 301 | IBM: screen lock | ||
| 302 | Lenovo: battery | ||
| 303 | |||
| 304 | 0x1004 0x03 FN+F4 Sleep button (ACPI sleep button | ||
| 305 | semanthics, i.e. sleep-to-RAM). | ||
| 306 | It is always generate some kind | ||
| 307 | of event, either the hot key | ||
| 308 | event or a ACPI sleep button | ||
| 309 | event. The firmware may | ||
| 310 | refuse to generate further FN+F4 | ||
| 311 | key presses until a S3 or S4 ACPI | ||
| 312 | sleep cycle is performed or some | ||
| 313 | time passes. | ||
| 314 | |||
| 315 | 0x1005 0x04 FN+F5 Radio. Enables/disables | ||
| 316 | the internal BlueTooth hardware | ||
| 317 | and W-WAN card if left in control | ||
| 318 | of the firmware. Does not affect | ||
| 319 | the WLAN card. | ||
| 320 | Should be used to turn on/off all | ||
| 321 | radios (bluetooth+W-WAN+WLAN), | ||
| 322 | really. | ||
| 323 | |||
| 324 | 0x1006 0x05 FN+F6 - | ||
| 325 | |||
| 326 | 0x1007 0x06 FN+F7 Video output cycle. | ||
| 327 | Do you feel lucky today? | ||
| 328 | |||
| 329 | 0x1008 0x07 FN+F8 IBM: toggle screen expand | ||
| 330 | Lenovo: configure ultranav | ||
| 331 | |||
| 332 | 0x1009 0x08 FN+F9 - | ||
| 333 | .. .. .. | ||
| 334 | 0x100B 0x0A FN+F11 - | ||
| 335 | |||
| 336 | 0x100C 0x0B FN+F12 Sleep to disk. You are always | ||
| 337 | supposed to handle it yourself, | ||
| 338 | either through the ACPI event, | ||
| 339 | or through a hotkey event. | ||
| 340 | The firmware may refuse to | ||
| 341 | generate further FN+F4 key | ||
| 342 | press events until a S3 or S4 | ||
| 343 | ACPI sleep cycle is performed, | ||
| 344 | or some time passes. | ||
| 345 | |||
| 346 | 0x100D 0x0C FN+BACKSPACE - | ||
| 347 | 0x100E 0x0D FN+INSERT - | ||
| 348 | 0x100F 0x0E FN+DELETE - | ||
| 349 | |||
| 350 | 0x1010 0x0F FN+HOME Brightness up. This key is | ||
| 351 | always handled by the firmware | ||
| 352 | in IBM ThinkPads, even when | ||
| 353 | unmasked. Just leave it alone. | ||
| 354 | For Lenovo ThinkPads with a new | ||
| 355 | BIOS, it has to be handled either | ||
| 356 | by the ACPI OSI, or by userspace. | ||
| 357 | 0x1011 0x10 FN+END Brightness down. See brightness | ||
| 358 | up for details. | ||
| 359 | |||
| 360 | 0x1012 0x11 FN+PGUP Thinklight toggle. This key is | ||
| 361 | always handled by the firmware, | ||
| 362 | even when unmasked. | ||
| 363 | |||
| 364 | 0x1013 0x12 FN+PGDOWN - | ||
| 365 | |||
| 366 | 0x1014 0x13 FN+SPACE Zoom key | ||
| 367 | |||
| 368 | 0x1015 0x14 VOLUME UP Internal mixer volume up. This | ||
| 369 | key is always handled by the | ||
| 370 | firmware, even when unmasked. | ||
| 371 | NOTE: Lenovo seems to be changing | ||
| 372 | this. | ||
| 373 | 0x1016 0x15 VOLUME DOWN Internal mixer volume up. This | ||
| 374 | key is always handled by the | ||
| 375 | firmware, even when unmasked. | ||
| 376 | NOTE: Lenovo seems to be changing | ||
| 377 | this. | ||
| 378 | 0x1017 0x16 MUTE Mute internal mixer. This | ||
| 379 | key is always handled by the | ||
| 380 | firmware, even when unmasked. | ||
| 381 | |||
| 382 | 0x1018 0x17 THINKPAD Thinkpad/Access IBM/Lenovo key | ||
| 383 | |||
| 384 | 0x1019 0x18 unknown | ||
| 385 | .. .. .. | ||
| 386 | 0x1020 0x1F unknown | ||
| 387 | |||
| 388 | The ThinkPad firmware does not allow one to differentiate when most hot | ||
| 389 | keys are pressed or released (either that, or we don't know how to, yet). | ||
| 390 | For these keys, the driver generates a set of events for a key press and | ||
| 391 | immediately issues the same set of events for a key release. It is | ||
| 392 | unknown by the driver if the ThinkPad firmware triggered these events on | ||
| 393 | hot key press or release, but the firmware will do it for either one, not | ||
| 394 | both. | ||
| 395 | |||
| 396 | If a key is mapped to KEY_RESERVED, it generates no input events at all, | ||
| 397 | and it may generate a legacy thinkpad-acpi ACPI hotkey event. | ||
| 398 | |||
| 399 | If a key is mapped to KEY_UNKNOWN, it generates an input event that | ||
| 400 | includes an scan code, and it may also generate a legacy thinkpad-acpi | ||
| 401 | ACPI hotkey event. | ||
| 402 | |||
| 403 | If a key is mapped to anything else, it will only generate legacy | ||
| 404 | thinkpad-acpi ACPI hotkey events if nobody has opened the input device. | ||
| 405 | |||
| 406 | Non hot-key ACPI HKEY event map: | ||
| 407 | 0x5001 Lid closed | ||
| 408 | 0x5002 Lid opened | ||
| 409 | 0x7000 Radio Switch may have changed state | ||
| 223 | 410 | ||
| 224 | 411 | ||
| 225 | Bluetooth | 412 | Bluetooth |
| @@ -437,27 +624,34 @@ CMOS control | |||
| 437 | procfs: /proc/acpi/ibm/cmos | 624 | procfs: /proc/acpi/ibm/cmos |
| 438 | sysfs device attribute: cmos_command | 625 | sysfs device attribute: cmos_command |
| 439 | 626 | ||
| 440 | This feature is used internally by the ACPI firmware to control the | 627 | This feature is mostly used internally by the ACPI firmware to keep the legacy |
| 441 | ThinkLight on most newer ThinkPad models. It may also control LCD | 628 | CMOS NVRAM bits in sync with the current machine state, and to record this |
| 442 | brightness, sounds volume and more, but only on some models. | 629 | state so that the ThinkPad will retain such settings across reboots. |
| 630 | |||
| 631 | Some of these commands actually perform actions in some ThinkPad models, but | ||
| 632 | this is expected to disappear more and more in newer models. As an example, in | ||
| 633 | a T43 and in a X40, commands 12 and 13 still control the ThinkLight state for | ||
| 634 | real, but commands 0 to 2 don't control the mixer anymore (they have been | ||
| 635 | phased out) and just update the NVRAM. | ||
| 443 | 636 | ||
| 444 | The range of valid cmos command numbers is 0 to 21, but not all have an | 637 | The range of valid cmos command numbers is 0 to 21, but not all have an |
| 445 | effect and the behavior varies from model to model. Here is the behavior | 638 | effect and the behavior varies from model to model. Here is the behavior |
| 446 | on the X40 (tpb is the ThinkPad Buttons utility): | 639 | on the X40 (tpb is the ThinkPad Buttons utility): |
| 447 | 640 | ||
| 448 | 0 - no effect but tpb reports "Volume down" | 641 | 0 - Related to "Volume down" key press |
| 449 | 1 - no effect but tpb reports "Volume up" | 642 | 1 - Related to "Volume up" key press |
| 450 | 2 - no effect but tpb reports "Mute on" | 643 | 2 - Related to "Mute on" key press |
| 451 | 3 - simulate pressing the "Access IBM" button | 644 | 3 - Related to "Access IBM" key press |
| 452 | 4 - LCD brightness up | 645 | 4 - Related to "LCD brightness up" key pess |
| 453 | 5 - LCD brightness down | 646 | 5 - Related to "LCD brightness down" key press |
| 454 | 11 - toggle screen expansion | 647 | 11 - Related to "toggle screen expansion" key press/function |
| 455 | 12 - ThinkLight on | 648 | 12 - Related to "ThinkLight on" |
| 456 | 13 - ThinkLight off | 649 | 13 - Related to "ThinkLight off" |
| 457 | 14 - no effect but tpb reports ThinkLight status change | 650 | 14 - Related to "ThinkLight" key press (toggle thinklight) |
| 458 | 651 | ||
| 459 | The cmos command interface is prone to firmware split-brain problems, as | 652 | The cmos command interface is prone to firmware split-brain problems, as |
| 460 | in newer ThinkPads it is just a compatibility layer. | 653 | in newer ThinkPads it is just a compatibility layer. Do not use it, it is |
| 654 | exported just as a debug tool. | ||
| 461 | 655 | ||
| 462 | LED control -- /proc/acpi/ibm/led | 656 | LED control -- /proc/acpi/ibm/led |
| 463 | --------------------------------- | 657 | --------------------------------- |
| @@ -516,23 +710,15 @@ Temperature sensors | |||
| 516 | procfs: /proc/acpi/ibm/thermal | 710 | procfs: /proc/acpi/ibm/thermal |
| 517 | sysfs device attributes: (hwmon) temp*_input | 711 | sysfs device attributes: (hwmon) temp*_input |
| 518 | 712 | ||
| 519 | Most ThinkPads include six or more separate temperature sensors but | 713 | Most ThinkPads include six or more separate temperature sensors but only |
| 520 | only expose the CPU temperature through the standard ACPI methods. | 714 | expose the CPU temperature through the standard ACPI methods. This |
| 521 | This feature shows readings from up to eight different sensors on older | 715 | feature shows readings from up to eight different sensors on older |
| 522 | ThinkPads, and it has experimental support for up to sixteen different | 716 | ThinkPads, and up to sixteen different sensors on newer ThinkPads. |
| 523 | sensors on newer ThinkPads. | ||
| 524 | |||
| 525 | EXPERIMENTAL: The 16-sensors feature is marked EXPERIMENTAL because the | ||
| 526 | implementation directly accesses hardware registers and may not work as | ||
| 527 | expected. USE WITH CAUTION! To use this feature, you need to supply the | ||
| 528 | experimental=1 parameter when loading the module. When EXPERIMENTAL | ||
| 529 | mode is enabled, reading the first 8 sensors on newer ThinkPads will | ||
| 530 | also use an new experimental thermal sensor access mode. | ||
| 531 | 717 | ||
| 532 | For example, on the X40, a typical output may be: | 718 | For example, on the X40, a typical output may be: |
| 533 | temperatures: 42 42 45 41 36 -128 33 -128 | 719 | temperatures: 42 42 45 41 36 -128 33 -128 |
| 534 | 720 | ||
| 535 | EXPERIMENTAL: On the T43/p, a typical output may be: | 721 | On the T43/p, a typical output may be: |
| 536 | temperatures: 48 48 36 52 38 -128 31 -128 48 52 48 -128 -128 -128 -128 -128 | 722 | temperatures: 48 48 36 52 38 -128 31 -128 48 52 48 -128 -128 -128 -128 -128 |
| 537 | 723 | ||
| 538 | The mapping of thermal sensors to physical locations varies depending on | 724 | The mapping of thermal sensors to physical locations varies depending on |
| @@ -562,7 +748,8 @@ http://thinkwiki.org/wiki/Thermal_Sensors#ThinkPad_T43.2C_T43p | |||
| 562 | 2: System board, left side (near PCMCIA slot), reported as HDAPS temp | 748 | 2: System board, left side (near PCMCIA slot), reported as HDAPS temp |
| 563 | 3: PCMCIA slot | 749 | 3: PCMCIA slot |
| 564 | 9: MCH (northbridge) to DRAM Bus | 750 | 9: MCH (northbridge) to DRAM Bus |
| 565 | 10: ICH (southbridge), under Mini-PCI card, under touchpad | 751 | 10: Clock-generator, mini-pci card and ICH (southbridge), under Mini-PCI |
| 752 | card, under touchpad | ||
| 566 | 11: Power regulator, underside of system board, below F2 key | 753 | 11: Power regulator, underside of system board, below F2 key |
| 567 | 754 | ||
| 568 | The A31 has a very atypical layout for the thermal sensors | 755 | The A31 has a very atypical layout for the thermal sensors |
| @@ -681,6 +868,12 @@ cannot be controlled. | |||
| 681 | The backlight control has eight levels, ranging from 0 to 7. Some of the | 868 | The backlight control has eight levels, ranging from 0 to 7. Some of the |
| 682 | levels may not be distinct. | 869 | levels may not be distinct. |
| 683 | 870 | ||
| 871 | There are two interfaces to the firmware for brightness control, EC and CMOS. | ||
| 872 | To select which one should be used, use the brightness_mode module parameter: | ||
| 873 | brightness_mode=1 selects EC mode, brightness_mode=2 selects CMOS mode, | ||
| 874 | brightness_mode=3 selects both EC and CMOS. The driver tries to autodetect | ||
| 875 | which interface to use. | ||
| 876 | |||
| 684 | Procfs notes: | 877 | Procfs notes: |
| 685 | 878 | ||
| 686 | The available commands are: | 879 | The available commands are: |
| @@ -976,3 +1169,9 @@ Sysfs interface changelog: | |||
| 976 | 1169 | ||
| 977 | 0x000100: Initial sysfs support, as a single platform driver and | 1170 | 0x000100: Initial sysfs support, as a single platform driver and |
| 978 | device. | 1171 | device. |
| 1172 | 0x000200: Hot key support for 32 hot keys, and radio slider switch | ||
| 1173 | support. | ||
| 1174 | 0x010000: Hot keys are now handled by default over the input | ||
| 1175 | layer, the radio switch generates input event EV_RADIO, | ||
| 1176 | and the driver enables hot key handling by default in | ||
| 1177 | the firmware. | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 773c732b4177..a9b9ef614ae7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -225,15 +225,15 @@ T: git kernel.org:/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6.git | |||
| 225 | S: Supported | 225 | S: Supported |
| 226 | 226 | ||
| 227 | ACPI BATTERY DRIVERS | 227 | ACPI BATTERY DRIVERS |
| 228 | P: Vladimir P. Lebedev | 228 | P: Alexey Starikovskiy |
| 229 | M: vladimir.p.lebedev@intel.com | 229 | M: astarikovskiy@suse.de |
| 230 | L: linux-acpi@vger.kernel.org | 230 | L: linux-acpi@vger.kernel.org |
| 231 | W: http://acpi.sourceforge.net/ | 231 | W: http://acpi.sourceforge.net/ |
| 232 | S: Supported | 232 | S: Supported |
| 233 | 233 | ||
| 234 | ACPI EC DRIVER | 234 | ACPI EC DRIVER |
| 235 | P: Alexey Starikovskiy | 235 | P: Alexey Starikovskiy |
| 236 | M: alexey.y.starikovskiy@linux.intel.com | 236 | M: astarikovskiy@suse.de |
| 237 | L: linux-acpi@vger.kernel.org | 237 | L: linux-acpi@vger.kernel.org |
| 238 | W: http://acpi.sourceforge.net/ | 238 | W: http://acpi.sourceforge.net/ |
| 239 | S: Supported | 239 | S: Supported |
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c index b87cedeaf59b..cacdd883bf2b 100644 --- a/arch/i386/kernel/acpi/boot.c +++ b/arch/i386/kernel/acpi/boot.c | |||
| @@ -986,14 +986,6 @@ static struct dmi_system_id __initdata acpi_dmi_table[] = { | |||
| 986 | }, | 986 | }, |
| 987 | { | 987 | { |
| 988 | .callback = force_acpi_ht, | 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 | .ident = "HP VISUALIZE NT Workstation", | 989 | .ident = "HP VISUALIZE NT Workstation", |
| 998 | .matches = { | 990 | .matches = { |
| 999 | DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"), | 991 | DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"), |
diff --git a/arch/i386/kernel/alternative.c b/arch/i386/kernel/alternative.c index 0695be538de5..c3750c2c4113 100644 --- a/arch/i386/kernel/alternative.c +++ b/arch/i386/kernel/alternative.c | |||
| @@ -2,8 +2,14 @@ | |||
| 2 | #include <linux/sched.h> | 2 | #include <linux/sched.h> |
| 3 | #include <linux/spinlock.h> | 3 | #include <linux/spinlock.h> |
| 4 | #include <linux/list.h> | 4 | #include <linux/list.h> |
| 5 | #include <linux/kprobes.h> | ||
| 6 | #include <linux/mm.h> | ||
| 7 | #include <linux/vmalloc.h> | ||
| 5 | #include <asm/alternative.h> | 8 | #include <asm/alternative.h> |
| 6 | #include <asm/sections.h> | 9 | #include <asm/sections.h> |
| 10 | #include <asm/pgtable.h> | ||
| 11 | #include <asm/mce.h> | ||
| 12 | #include <asm/nmi.h> | ||
| 7 | 13 | ||
| 8 | #ifdef CONFIG_HOTPLUG_CPU | 14 | #ifdef CONFIG_HOTPLUG_CPU |
| 9 | static int smp_alt_once; | 15 | static int smp_alt_once; |
| @@ -150,7 +156,7 @@ static void nop_out(void *insns, unsigned int len) | |||
| 150 | unsigned int noplen = len; | 156 | unsigned int noplen = len; |
| 151 | if (noplen > ASM_NOP_MAX) | 157 | if (noplen > ASM_NOP_MAX) |
| 152 | noplen = ASM_NOP_MAX; | 158 | noplen = ASM_NOP_MAX; |
| 153 | memcpy(insns, noptable[noplen], noplen); | 159 | text_poke(insns, noptable[noplen], noplen); |
| 154 | insns += noplen; | 160 | insns += noplen; |
| 155 | len -= noplen; | 161 | len -= noplen; |
| 156 | } | 162 | } |
| @@ -202,7 +208,7 @@ static void alternatives_smp_lock(u8 **start, u8 **end, u8 *text, u8 *text_end) | |||
| 202 | continue; | 208 | continue; |
| 203 | if (*ptr > text_end) | 209 | if (*ptr > text_end) |
| 204 | continue; | 210 | continue; |
| 205 | **ptr = 0xf0; /* lock prefix */ | 211 | text_poke(*ptr, ((unsigned char []){0xf0}), 1); /* add lock prefix */ |
| 206 | }; | 212 | }; |
| 207 | } | 213 | } |
| 208 | 214 | ||
| @@ -360,10 +366,6 @@ void apply_paravirt(struct paravirt_patch_site *start, | |||
| 360 | /* Pad the rest with nops */ | 366 | /* Pad the rest with nops */ |
| 361 | nop_out(p->instr + used, p->len - used); | 367 | nop_out(p->instr + used, p->len - used); |
| 362 | } | 368 | } |
| 363 | |||
| 364 | /* Sync to be conservative, in case we patched following | ||
| 365 | * instructions */ | ||
| 366 | sync_core(); | ||
| 367 | } | 369 | } |
| 368 | extern struct paravirt_patch_site __start_parainstructions[], | 370 | extern struct paravirt_patch_site __start_parainstructions[], |
| 369 | __stop_parainstructions[]; | 371 | __stop_parainstructions[]; |
| @@ -373,6 +375,14 @@ void __init alternative_instructions(void) | |||
| 373 | { | 375 | { |
| 374 | unsigned long flags; | 376 | unsigned long flags; |
| 375 | 377 | ||
| 378 | /* The patching is not fully atomic, so try to avoid local interruptions | ||
| 379 | that might execute the to be patched code. | ||
| 380 | Other CPUs are not running. */ | ||
| 381 | stop_nmi(); | ||
| 382 | #ifdef CONFIG_MCE | ||
| 383 | stop_mce(); | ||
| 384 | #endif | ||
| 385 | |||
| 376 | local_irq_save(flags); | 386 | local_irq_save(flags); |
| 377 | apply_alternatives(__alt_instructions, __alt_instructions_end); | 387 | apply_alternatives(__alt_instructions, __alt_instructions_end); |
| 378 | 388 | ||
| @@ -405,4 +415,37 @@ void __init alternative_instructions(void) | |||
| 405 | #endif | 415 | #endif |
| 406 | apply_paravirt(__parainstructions, __parainstructions_end); | 416 | apply_paravirt(__parainstructions, __parainstructions_end); |
| 407 | local_irq_restore(flags); | 417 | local_irq_restore(flags); |
| 418 | |||
| 419 | restart_nmi(); | ||
| 420 | #ifdef CONFIG_MCE | ||
| 421 | restart_mce(); | ||
| 422 | #endif | ||
| 423 | } | ||
| 424 | |||
| 425 | /* | ||
| 426 | * Warning: | ||
| 427 | * When you use this code to patch more than one byte of an instruction | ||
| 428 | * you need to make sure that other CPUs cannot execute this code in parallel. | ||
| 429 | * Also no thread must be currently preempted in the middle of these instructions. | ||
| 430 | * And on the local CPU you need to be protected again NMI or MCE handlers | ||
| 431 | * seeing an inconsistent instruction while you patch. | ||
| 432 | */ | ||
| 433 | void __kprobes text_poke(void *oaddr, unsigned char *opcode, int len) | ||
| 434 | { | ||
| 435 | u8 *addr = oaddr; | ||
| 436 | if (!pte_write(*lookup_address((unsigned long)addr))) { | ||
| 437 | struct page *p[2] = { virt_to_page(addr), virt_to_page(addr+PAGE_SIZE) }; | ||
| 438 | addr = vmap(p, 2, VM_MAP, PAGE_KERNEL); | ||
| 439 | if (!addr) | ||
| 440 | return; | ||
| 441 | addr += ((unsigned long)oaddr) % PAGE_SIZE; | ||
| 442 | } | ||
| 443 | memcpy(addr, opcode, len); | ||
| 444 | sync_core(); | ||
| 445 | /* Not strictly needed, but can speed CPU recovery up. Ignore cross cacheline | ||
| 446 | case. */ | ||
| 447 | if (cpu_has_clflush) | ||
| 448 | asm("clflush (%0) " :: "r" (oaddr) : "memory"); | ||
| 449 | if (addr != oaddr) | ||
| 450 | vunmap(addr); | ||
| 408 | } | 451 | } |
diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c index 815a5f0aa474..c7ba455d5ac7 100644 --- a/arch/i386/kernel/cpu/amd.c +++ b/arch/i386/kernel/cpu/amd.c | |||
| @@ -231,6 +231,9 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) | |||
| 231 | 231 | ||
| 232 | switch (c->x86) { | 232 | switch (c->x86) { |
| 233 | case 15: | 233 | case 15: |
| 234 | /* Use K8 tuning for Fam10h and Fam11h */ | ||
| 235 | case 0x10: | ||
| 236 | case 0x11: | ||
| 234 | set_bit(X86_FEATURE_K8, c->x86_capability); | 237 | set_bit(X86_FEATURE_K8, c->x86_capability); |
| 235 | break; | 238 | break; |
| 236 | case 6: | 239 | case 6: |
diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c index 18c8b67ea3a7..6f846bee2103 100644 --- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c | |||
| @@ -665,8 +665,8 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
| 665 | data->max_freq = perf->states[0].core_frequency * 1000; | 665 | data->max_freq = perf->states[0].core_frequency * 1000; |
| 666 | /* table init */ | 666 | /* table init */ |
| 667 | for (i=0; i<perf->state_count; i++) { | 667 | for (i=0; i<perf->state_count; i++) { |
| 668 | if (i>0 && perf->states[i].core_frequency == | 668 | if (i>0 && perf->states[i].core_frequency >= |
| 669 | perf->states[i-1].core_frequency) | 669 | data->freq_table[valid_states-1].frequency / 1000) |
| 670 | continue; | 670 | continue; |
| 671 | 671 | ||
| 672 | data->freq_table[valid_states].index = i; | 672 | data->freq_table[valid_states].index = i; |
diff --git a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c index 194144539a6f..461dabc4e495 100644 --- a/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c +++ b/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c | |||
| @@ -79,7 +79,7 @@ | |||
| 79 | #include <linux/smp.h> | 79 | #include <linux/smp.h> |
| 80 | #include <linux/cpufreq.h> | 80 | #include <linux/cpufreq.h> |
| 81 | #include <linux/pci.h> | 81 | #include <linux/pci.h> |
| 82 | #include <asm/processor.h> | 82 | #include <asm/processor-cyrix.h> |
| 83 | #include <asm/errno.h> | 83 | #include <asm/errno.h> |
| 84 | 84 | ||
| 85 | /* PCI config registers, all at F0 */ | 85 | /* PCI config registers, all at F0 */ |
diff --git a/arch/i386/kernel/cpu/cyrix.c b/arch/i386/kernel/cpu/cyrix.c index e88d2fba156b..122d2d75aa9f 100644 --- a/arch/i386/kernel/cpu/cyrix.c +++ b/arch/i386/kernel/cpu/cyrix.c | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | #include <linux/pci.h> | 4 | #include <linux/pci.h> |
| 5 | #include <asm/dma.h> | 5 | #include <asm/dma.h> |
| 6 | #include <asm/io.h> | 6 | #include <asm/io.h> |
| 7 | #include <asm/processor.h> | 7 | #include <asm/processor-cyrix.h> |
| 8 | #include <asm/timer.h> | 8 | #include <asm/timer.h> |
| 9 | #include <asm/pci-direct.h> | 9 | #include <asm/pci-direct.h> |
| 10 | #include <asm/tsc.h> | 10 | #include <asm/tsc.h> |
diff --git a/arch/i386/kernel/cpu/mcheck/mce.c b/arch/i386/kernel/cpu/mcheck/mce.c index 56cd485b127c..34c781eddee4 100644 --- a/arch/i386/kernel/cpu/mcheck/mce.c +++ b/arch/i386/kernel/cpu/mcheck/mce.c | |||
| @@ -60,6 +60,20 @@ void mcheck_init(struct cpuinfo_x86 *c) | |||
| 60 | } | 60 | } |
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | static unsigned long old_cr4 __initdata; | ||
| 64 | |||
| 65 | void __init stop_mce(void) | ||
| 66 | { | ||
| 67 | old_cr4 = read_cr4(); | ||
| 68 | clear_in_cr4(X86_CR4_MCE); | ||
| 69 | } | ||
| 70 | |||
| 71 | void __init restart_mce(void) | ||
| 72 | { | ||
| 73 | if (old_cr4 & X86_CR4_MCE) | ||
| 74 | set_in_cr4(X86_CR4_MCE); | ||
| 75 | } | ||
| 76 | |||
| 63 | static int __init mcheck_disable(char *str) | 77 | static int __init mcheck_disable(char *str) |
| 64 | { | 78 | { |
| 65 | mce_disabled = 1; | 79 | mce_disabled = 1; |
diff --git a/arch/i386/kernel/cpu/mtrr/cyrix.c b/arch/i386/kernel/cpu/mtrr/cyrix.c index 1001f1e0fe6d..2287d4863a8a 100644 --- a/arch/i386/kernel/cpu/mtrr/cyrix.c +++ b/arch/i386/kernel/cpu/mtrr/cyrix.c | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | #include <asm/mtrr.h> | 3 | #include <asm/mtrr.h> |
| 4 | #include <asm/msr.h> | 4 | #include <asm/msr.h> |
| 5 | #include <asm/io.h> | 5 | #include <asm/io.h> |
| 6 | #include <asm/processor-cyrix.h> | ||
| 6 | #include "mtrr.h" | 7 | #include "mtrr.h" |
| 7 | 8 | ||
| 8 | int arr3_protected; | 9 | int arr3_protected; |
diff --git a/arch/i386/kernel/cpu/mtrr/state.c b/arch/i386/kernel/cpu/mtrr/state.c index 7b39a2f954d9..c9014ca4a575 100644 --- a/arch/i386/kernel/cpu/mtrr/state.c +++ b/arch/i386/kernel/cpu/mtrr/state.c | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | #include <asm/io.h> | 3 | #include <asm/io.h> |
| 4 | #include <asm/mtrr.h> | 4 | #include <asm/mtrr.h> |
| 5 | #include <asm/msr.h> | 5 | #include <asm/msr.h> |
| 6 | #include <asm-i386/processor-cyrix.h> | ||
| 6 | #include "mtrr.h" | 7 | #include "mtrr.h" |
| 7 | 8 | ||
| 8 | 9 | ||
diff --git a/arch/i386/kernel/cpu/perfctr-watchdog.c b/arch/i386/kernel/cpu/perfctr-watchdog.c index 30b5e48aa76b..4be488e73bee 100644 --- a/arch/i386/kernel/cpu/perfctr-watchdog.c +++ b/arch/i386/kernel/cpu/perfctr-watchdog.c | |||
| @@ -325,7 +325,7 @@ static struct wd_ops k7_wd_ops = { | |||
| 325 | .stop = single_msr_stop_watchdog, | 325 | .stop = single_msr_stop_watchdog, |
| 326 | .perfctr = MSR_K7_PERFCTR0, | 326 | .perfctr = MSR_K7_PERFCTR0, |
| 327 | .evntsel = MSR_K7_EVNTSEL0, | 327 | .evntsel = MSR_K7_EVNTSEL0, |
| 328 | .checkbit = 1ULL<<63, | 328 | .checkbit = 1ULL<<47, |
| 329 | }; | 329 | }; |
| 330 | 330 | ||
| 331 | /* Intel Model 6 (PPro+,P2,P3,P-M,Core1) */ | 331 | /* Intel Model 6 (PPro+,P2,P3,P-M,Core1) */ |
| @@ -346,7 +346,9 @@ static int setup_p6_watchdog(unsigned nmi_hz) | |||
| 346 | perfctr_msr = MSR_P6_PERFCTR0; | 346 | perfctr_msr = MSR_P6_PERFCTR0; |
| 347 | evntsel_msr = MSR_P6_EVNTSEL0; | 347 | evntsel_msr = MSR_P6_EVNTSEL0; |
| 348 | 348 | ||
| 349 | wrmsrl(perfctr_msr, 0UL); | 349 | /* KVM doesn't implement this MSR */ |
| 350 | if (wrmsr_safe(perfctr_msr, 0, 0) < 0) | ||
| 351 | return 0; | ||
| 350 | 352 | ||
| 351 | evntsel = P6_EVNTSEL_INT | 353 | evntsel = P6_EVNTSEL_INT |
| 352 | | P6_EVNTSEL_OS | 354 | | P6_EVNTSEL_OS |
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c index dde828a333c3..448a50b1324c 100644 --- a/arch/i386/kernel/kprobes.c +++ b/arch/i386/kernel/kprobes.c | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | #include <asm/cacheflush.h> | 35 | #include <asm/cacheflush.h> |
| 36 | #include <asm/desc.h> | 36 | #include <asm/desc.h> |
| 37 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
| 38 | #include <asm/alternative.h> | ||
| 38 | 39 | ||
| 39 | void jprobe_return_end(void); | 40 | void jprobe_return_end(void); |
| 40 | 41 | ||
| @@ -169,16 +170,12 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) | |||
| 169 | 170 | ||
| 170 | void __kprobes arch_arm_kprobe(struct kprobe *p) | 171 | void __kprobes arch_arm_kprobe(struct kprobe *p) |
| 171 | { | 172 | { |
| 172 | *p->addr = BREAKPOINT_INSTRUCTION; | 173 | text_poke(p->addr, ((unsigned char []){BREAKPOINT_INSTRUCTION}), 1); |
| 173 | flush_icache_range((unsigned long) p->addr, | ||
| 174 | (unsigned long) p->addr + sizeof(kprobe_opcode_t)); | ||
| 175 | } | 174 | } |
| 176 | 175 | ||
| 177 | void __kprobes arch_disarm_kprobe(struct kprobe *p) | 176 | void __kprobes arch_disarm_kprobe(struct kprobe *p) |
| 178 | { | 177 | { |
| 179 | *p->addr = p->opcode; | 178 | text_poke(p->addr, &p->opcode, 1); |
| 180 | flush_icache_range((unsigned long) p->addr, | ||
| 181 | (unsigned long) p->addr + sizeof(kprobe_opcode_t)); | ||
| 182 | } | 179 | } |
| 183 | 180 | ||
| 184 | void __kprobes arch_remove_kprobe(struct kprobe *p) | 181 | void __kprobes arch_remove_kprobe(struct kprobe *p) |
diff --git a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c index 03b7f5584d71..99beac7f96ce 100644 --- a/arch/i386/kernel/nmi.c +++ b/arch/i386/kernel/nmi.c | |||
| @@ -353,7 +353,7 @@ __kprobes int nmi_watchdog_tick(struct pt_regs * regs, unsigned reason) | |||
| 353 | * Take the local apic timer and PIT/HPET into account. We don't | 353 | * Take the local apic timer and PIT/HPET into account. We don't |
| 354 | * know which one is active, when we have highres/dyntick on | 354 | * know which one is active, when we have highres/dyntick on |
| 355 | */ | 355 | */ |
| 356 | sum = per_cpu(irq_stat, cpu).apic_timer_irqs + kstat_irqs(0); | 356 | sum = per_cpu(irq_stat, cpu).apic_timer_irqs + kstat_cpu(cpu).irqs[0]; |
| 357 | 357 | ||
| 358 | /* if the none of the timers isn't firing, this cpu isn't doing much */ | 358 | /* if the none of the timers isn't firing, this cpu isn't doing much */ |
| 359 | if (!touched && last_irq_sums[cpu] == sum) { | 359 | if (!touched && last_irq_sums[cpu] == sum) { |
diff --git a/arch/i386/kernel/paravirt.c b/arch/i386/kernel/paravirt.c index 53f07a8275e3..ea962c0667d5 100644 --- a/arch/i386/kernel/paravirt.c +++ b/arch/i386/kernel/paravirt.c | |||
| @@ -124,20 +124,28 @@ unsigned paravirt_patch_ignore(unsigned len) | |||
| 124 | return len; | 124 | return len; |
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | struct branch { | ||
| 128 | unsigned char opcode; | ||
| 129 | u32 delta; | ||
| 130 | } __attribute__((packed)); | ||
| 131 | |||
| 127 | unsigned paravirt_patch_call(void *target, u16 tgt_clobbers, | 132 | unsigned paravirt_patch_call(void *target, u16 tgt_clobbers, |
| 128 | void *site, u16 site_clobbers, | 133 | void *site, u16 site_clobbers, |
| 129 | unsigned len) | 134 | unsigned len) |
| 130 | { | 135 | { |
| 131 | unsigned char *call = site; | 136 | unsigned char *call = site; |
| 132 | unsigned long delta = (unsigned long)target - (unsigned long)(call+5); | 137 | unsigned long delta = (unsigned long)target - (unsigned long)(call+5); |
| 138 | struct branch b; | ||
| 133 | 139 | ||
| 134 | if (tgt_clobbers & ~site_clobbers) | 140 | if (tgt_clobbers & ~site_clobbers) |
| 135 | return len; /* target would clobber too much for this site */ | 141 | return len; /* target would clobber too much for this site */ |
| 136 | if (len < 5) | 142 | if (len < 5) |
| 137 | return len; /* call too long for patch site */ | 143 | return len; /* call too long for patch site */ |
| 138 | 144 | ||
| 139 | *call++ = 0xe8; /* call */ | 145 | b.opcode = 0xe8; /* call */ |
| 140 | *(unsigned long *)call = delta; | 146 | b.delta = delta; |
| 147 | BUILD_BUG_ON(sizeof(b) != 5); | ||
| 148 | text_poke(call, (unsigned char *)&b, 5); | ||
| 141 | 149 | ||
| 142 | return 5; | 150 | return 5; |
| 143 | } | 151 | } |
| @@ -146,12 +154,14 @@ unsigned paravirt_patch_jmp(void *target, void *site, unsigned len) | |||
| 146 | { | 154 | { |
| 147 | unsigned char *jmp = site; | 155 | unsigned char *jmp = site; |
| 148 | unsigned long delta = (unsigned long)target - (unsigned long)(jmp+5); | 156 | unsigned long delta = (unsigned long)target - (unsigned long)(jmp+5); |
| 157 | struct branch b; | ||
| 149 | 158 | ||
| 150 | if (len < 5) | 159 | if (len < 5) |
| 151 | return len; /* call too long for patch site */ | 160 | return len; /* call too long for patch site */ |
| 152 | 161 | ||
| 153 | *jmp++ = 0xe9; /* jmp */ | 162 | b.opcode = 0xe9; /* jmp */ |
| 154 | *(unsigned long *)jmp = delta; | 163 | b.delta = delta; |
| 164 | text_poke(jmp, (unsigned char *)&b, 5); | ||
| 155 | 165 | ||
| 156 | return 5; | 166 | return 5; |
| 157 | } | 167 | } |
diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c index d574e38f0f77..f5dd85656c18 100644 --- a/arch/i386/kernel/signal.c +++ b/arch/i386/kernel/signal.c | |||
| @@ -199,6 +199,13 @@ asmlinkage int sys_sigreturn(unsigned long __unused) | |||
| 199 | return eax; | 199 | return eax; |
| 200 | 200 | ||
| 201 | badframe: | 201 | badframe: |
| 202 | if (show_unhandled_signals && printk_ratelimit()) | ||
| 203 | printk("%s%s[%d] bad frame in sigreturn frame:%p eip:%lx" | ||
| 204 | " esp:%lx oeax:%lx\n", | ||
| 205 | current->pid > 1 ? KERN_INFO : KERN_EMERG, | ||
| 206 | current->comm, current->pid, frame, regs->eip, | ||
| 207 | regs->esp, regs->orig_eax); | ||
| 208 | |||
| 202 | force_sig(SIGSEGV, current); | 209 | force_sig(SIGSEGV, current); |
| 203 | return 0; | 210 | return 0; |
| 204 | } | 211 | } |
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 5910d3fac561..e4f61d1c6248 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c | |||
| @@ -308,7 +308,7 @@ cpumask_t cpu_coregroup_map(int cpu) | |||
| 308 | /* representing cpus for which sibling maps can be computed */ | 308 | /* representing cpus for which sibling maps can be computed */ |
| 309 | static cpumask_t cpu_sibling_setup_map; | 309 | static cpumask_t cpu_sibling_setup_map; |
| 310 | 310 | ||
| 311 | void set_cpu_sibling_map(int cpu) | 311 | void __cpuinit set_cpu_sibling_map(int cpu) |
| 312 | { | 312 | { |
| 313 | int i; | 313 | int i; |
| 314 | struct cpuinfo_x86 *c = cpu_data; | 314 | struct cpuinfo_x86 *c = cpu_data; |
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 57772a18c394..cfffe3dd9e83 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c | |||
| @@ -618,6 +618,13 @@ fastcall void __kprobes do_general_protection(struct pt_regs * regs, | |||
| 618 | 618 | ||
| 619 | current->thread.error_code = error_code; | 619 | current->thread.error_code = error_code; |
| 620 | current->thread.trap_no = 13; | 620 | current->thread.trap_no = 13; |
| 621 | if (show_unhandled_signals && unhandled_signal(current, SIGSEGV) && | ||
| 622 | printk_ratelimit()) | ||
| 623 | printk(KERN_INFO | ||
| 624 | "%s[%d] general protection eip:%lx esp:%lx error:%lx\n", | ||
| 625 | current->comm, current->pid, | ||
| 626 | regs->eip, regs->esp, error_code); | ||
| 627 | |||
| 621 | force_sig(SIGSEGV, current); | 628 | force_sig(SIGSEGV, current); |
| 622 | return; | 629 | return; |
| 623 | 630 | ||
| @@ -768,6 +775,8 @@ static __kprobes void default_do_nmi(struct pt_regs * regs) | |||
| 768 | reassert_nmi(); | 775 | reassert_nmi(); |
| 769 | } | 776 | } |
| 770 | 777 | ||
| 778 | static int ignore_nmis; | ||
| 779 | |||
| 771 | fastcall __kprobes void do_nmi(struct pt_regs * regs, long error_code) | 780 | fastcall __kprobes void do_nmi(struct pt_regs * regs, long error_code) |
| 772 | { | 781 | { |
| 773 | int cpu; | 782 | int cpu; |
| @@ -778,11 +787,24 @@ fastcall __kprobes void do_nmi(struct pt_regs * regs, long error_code) | |||
| 778 | 787 | ||
| 779 | ++nmi_count(cpu); | 788 | ++nmi_count(cpu); |
| 780 | 789 | ||
| 781 | default_do_nmi(regs); | 790 | if (!ignore_nmis) |
| 791 | default_do_nmi(regs); | ||
| 782 | 792 | ||
| 783 | nmi_exit(); | 793 | nmi_exit(); |
| 784 | } | 794 | } |
| 785 | 795 | ||
| 796 | void stop_nmi(void) | ||
| 797 | { | ||
| 798 | acpi_nmi_disable(); | ||
| 799 | ignore_nmis++; | ||
| 800 | } | ||
| 801 | |||
| 802 | void restart_nmi(void) | ||
| 803 | { | ||
| 804 | ignore_nmis--; | ||
| 805 | acpi_nmi_enable(); | ||
| 806 | } | ||
| 807 | |||
| 786 | #ifdef CONFIG_KPROBES | 808 | #ifdef CONFIG_KPROBES |
| 787 | fastcall void __kprobes do_int3(struct pt_regs *regs, long error_code) | 809 | fastcall void __kprobes do_int3(struct pt_regs *regs, long error_code) |
| 788 | { | 810 | { |
diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c index e92a10124935..01ffdd4964f0 100644 --- a/arch/i386/mm/fault.c +++ b/arch/i386/mm/fault.c | |||
| @@ -283,6 +283,8 @@ static inline int vmalloc_fault(unsigned long address) | |||
| 283 | return 0; | 283 | return 0; |
| 284 | } | 284 | } |
| 285 | 285 | ||
| 286 | int show_unhandled_signals = 1; | ||
| 287 | |||
| 286 | /* | 288 | /* |
| 287 | * This routine handles page faults. It determines the address, | 289 | * This routine handles page faults. It determines the address, |
| 288 | * and the problem, and then passes it off to one of the appropriate | 290 | * and the problem, and then passes it off to one of the appropriate |
| @@ -469,6 +471,14 @@ bad_area_nosemaphore: | |||
| 469 | if (is_prefetch(regs, address, error_code)) | 471 | if (is_prefetch(regs, address, error_code)) |
| 470 | return; | 472 | return; |
| 471 | 473 | ||
| 474 | if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) && | ||
| 475 | printk_ratelimit()) { | ||
| 476 | printk("%s%s[%d]: segfault at %08lx eip %08lx " | ||
| 477 | "esp %08lx error %lx\n", | ||
| 478 | tsk->pid > 1 ? KERN_INFO : KERN_EMERG, | ||
| 479 | tsk->comm, tsk->pid, address, regs->eip, | ||
| 480 | regs->esp, error_code); | ||
| 481 | } | ||
| 472 | tsk->thread.cr2 = address; | 482 | tsk->thread.cr2 = address; |
| 473 | /* Kernel addresses are always protection faults */ | 483 | /* Kernel addresses are always protection faults */ |
| 474 | tsk->thread.error_code = error_code | (address >= TASK_SIZE); | 484 | tsk->thread.error_code = error_code | (address >= TASK_SIZE); |
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index e1a9a805c445..c3b9905af2d5 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c | |||
| @@ -800,17 +800,9 @@ void mark_rodata_ro(void) | |||
| 800 | unsigned long start = PFN_ALIGN(_text); | 800 | unsigned long start = PFN_ALIGN(_text); |
| 801 | unsigned long size = PFN_ALIGN(_etext) - start; | 801 | unsigned long size = PFN_ALIGN(_etext) - start; |
| 802 | 802 | ||
| 803 | #ifndef CONFIG_KPROBES | 803 | change_page_attr(virt_to_page(start), |
| 804 | #ifdef CONFIG_HOTPLUG_CPU | 804 | size >> PAGE_SHIFT, PAGE_KERNEL_RX); |
| 805 | /* It must still be possible to apply SMP alternatives. */ | 805 | printk("Write protecting the kernel text: %luk\n", size >> 10); |
| 806 | if (num_possible_cpus() <= 1) | ||
| 807 | #endif | ||
| 808 | { | ||
| 809 | change_page_attr(virt_to_page(start), | ||
| 810 | size >> PAGE_SHIFT, PAGE_KERNEL_RX); | ||
| 811 | printk("Write protecting the kernel text: %luk\n", size >> 10); | ||
| 812 | } | ||
| 813 | #endif | ||
| 814 | start += size; | 806 | start += size; |
| 815 | size = (unsigned long)__end_rodata - start; | 807 | size = (unsigned long)__end_rodata - start; |
| 816 | change_page_attr(virt_to_page(start), | 808 | change_page_attr(virt_to_page(start), |
diff --git a/arch/i386/xen/xen-head.S b/arch/i386/xen/xen-head.S index 2998d55a0017..bc71f3bc4014 100644 --- a/arch/i386/xen/xen-head.S +++ b/arch/i386/xen/xen-head.S | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <asm/boot.h> | 7 | #include <asm/boot.h> |
| 8 | #include <xen/interface/elfnote.h> | 8 | #include <xen/interface/elfnote.h> |
| 9 | 9 | ||
| 10 | .section .init.text | ||
| 10 | ENTRY(startup_xen) | 11 | ENTRY(startup_xen) |
| 11 | movl %esi,xen_start_info | 12 | movl %esi,xen_start_info |
| 12 | cld | 13 | cld |
| @@ -19,6 +20,7 @@ ENTRY(hypercall_page) | |||
| 19 | .skip 0x1000 | 20 | .skip 0x1000 |
| 20 | .popsection | 21 | .popsection |
| 21 | 22 | ||
| 23 | .section .text | ||
| 22 | ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS, .asciz "linux") | 24 | ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS, .asciz "linux") |
| 23 | ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION, .asciz "2.6") | 25 | ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION, .asciz "2.6") |
| 24 | ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION, .asciz "xen-3.0") | 26 | ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION, .asciz "xen-3.0") |
diff --git a/arch/powerpc/configs/prpmc2800_defconfig b/arch/powerpc/configs/prpmc2800_defconfig index fb504a714625..858f865f2d59 100644 --- a/arch/powerpc/configs/prpmc2800_defconfig +++ b/arch/powerpc/configs/prpmc2800_defconfig | |||
| @@ -48,7 +48,7 @@ CONFIG_PPC_STD_MMU_32=y | |||
| 48 | # CONFIG_PPC_MM_SLICES is not set | 48 | # CONFIG_PPC_MM_SLICES is not set |
| 49 | # CONFIG_SMP is not set | 49 | # CONFIG_SMP is not set |
| 50 | CONFIG_NOT_COHERENT_CACHE=y | 50 | CONFIG_NOT_COHERENT_CACHE=y |
| 51 | CONFIG_CONFIG_CHECK_CACHE_COHERENCY=y | 51 | CONFIG_CHECK_CACHE_COHERENCY=y |
| 52 | CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" | 52 | CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" |
| 53 | 53 | ||
| 54 | # | 54 | # |
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 94b4a028232a..fe7d1255e11e 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c | |||
| @@ -166,7 +166,7 @@ int pcibios_add_platform_entries(struct pci_dev *pdev) | |||
| 166 | 166 | ||
| 167 | } | 167 | } |
| 168 | 168 | ||
| 169 | char __init *pcibios_setup(char *str) | 169 | char __devinit *pcibios_setup(char *str) |
| 170 | { | 170 | { |
| 171 | return str; | 171 | return str; |
| 172 | } | 172 | } |
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index bdcd23d8d8b9..a38197b12d3e 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
| @@ -1218,7 +1218,7 @@ void of_attach_node(struct device_node *np) | |||
| 1218 | * a reference to the node. The memory associated with the node | 1218 | * a reference to the node. The memory associated with the node |
| 1219 | * is not freed until its refcount goes to zero. | 1219 | * is not freed until its refcount goes to zero. |
| 1220 | */ | 1220 | */ |
| 1221 | void of_detach_node(const struct device_node *np) | 1221 | void of_detach_node(struct device_node *np) |
| 1222 | { | 1222 | { |
| 1223 | struct device_node *parent; | 1223 | struct device_node *parent; |
| 1224 | 1224 | ||
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index d577b71db375..087c92f2a3eb 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c | |||
| @@ -284,7 +284,7 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info, int | |||
| 284 | int wait) | 284 | int wait) |
| 285 | { | 285 | { |
| 286 | cpumask_t map = CPU_MASK_NONE; | 286 | cpumask_t map = CPU_MASK_NONE; |
| 287 | int ret = -EBUSY; | 287 | int ret = 0; |
| 288 | 288 | ||
| 289 | if (!cpu_online(cpu)) | 289 | if (!cpu_online(cpu)) |
| 290 | return -EINVAL; | 290 | return -EINVAL; |
| @@ -292,6 +292,11 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info, int | |||
| 292 | cpu_set(cpu, map); | 292 | cpu_set(cpu, map); |
| 293 | if (cpu != get_cpu()) | 293 | if (cpu != get_cpu()) |
| 294 | ret = smp_call_function_map(func,info,nonatomic,wait,map); | 294 | ret = smp_call_function_map(func,info,nonatomic,wait,map); |
| 295 | else { | ||
| 296 | local_irq_disable(); | ||
| 297 | func(info); | ||
| 298 | local_irq_enable(); | ||
| 299 | } | ||
| 295 | put_cpu(); | 300 | put_cpu(); |
| 296 | return ret; | 301 | return ret; |
| 297 | } | 302 | } |
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index 3767211b3d0f..ab3546c5ac3a 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c | |||
| @@ -283,7 +283,13 @@ good_area: | |||
| 283 | /* protection fault */ | 283 | /* protection fault */ |
| 284 | if (error_code & DSISR_PROTFAULT) | 284 | if (error_code & DSISR_PROTFAULT) |
| 285 | goto bad_area; | 285 | goto bad_area; |
| 286 | if (!(vma->vm_flags & VM_EXEC)) | 286 | /* |
| 287 | * Allow execution from readable areas if the MMU does not | ||
| 288 | * provide separate controls over reading and executing. | ||
| 289 | */ | ||
| 290 | if (!(vma->vm_flags & VM_EXEC) && | ||
| 291 | (cpu_has_feature(CPU_FTR_NOEXECUTE) || | ||
| 292 | !(vma->vm_flags & (VM_READ | VM_WRITE)))) | ||
| 287 | goto bad_area; | 293 | goto bad_area; |
| 288 | #else | 294 | #else |
| 289 | pte_t *ptep; | 295 | pte_t *ptep; |
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 2ce9491b48d4..bc7b0cedae5e 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
| @@ -609,7 +609,7 @@ static void demote_segment_4k(struct mm_struct *mm, unsigned long addr) | |||
| 609 | mm->context.sllp = SLB_VSID_USER | mmu_psize_defs[MMU_PAGE_4K].sllp; | 609 | mm->context.sllp = SLB_VSID_USER | mmu_psize_defs[MMU_PAGE_4K].sllp; |
| 610 | #endif /* CONFIG_PPC_MM_SLICES */ | 610 | #endif /* CONFIG_PPC_MM_SLICES */ |
| 611 | 611 | ||
| 612 | #ifdef CONFIG_SPE_BASE | 612 | #ifdef CONFIG_SPU_BASE |
| 613 | spu_flush_all_slbs(mm); | 613 | spu_flush_all_slbs(mm); |
| 614 | #endif | 614 | #endif |
| 615 | } | 615 | } |
| @@ -744,7 +744,7 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap) | |||
| 744 | "to 4kB pages because of " | 744 | "to 4kB pages because of " |
| 745 | "non-cacheable mapping\n"); | 745 | "non-cacheable mapping\n"); |
| 746 | psize = mmu_vmalloc_psize = MMU_PAGE_4K; | 746 | psize = mmu_vmalloc_psize = MMU_PAGE_4K; |
| 747 | #ifdef CONFIG_SPE_BASE | 747 | #ifdef CONFIG_SPU_BASE |
| 748 | spu_flush_all_slbs(mm); | 748 | spu_flush_all_slbs(mm); |
| 749 | #endif | 749 | #endif |
| 750 | } | 750 | } |
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index b8b5fde94668..e4b2aee53a73 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype | |||
| @@ -215,7 +215,7 @@ config NOT_COHERENT_CACHE | |||
| 215 | depends on 4xx || 8xx || E200 | 215 | depends on 4xx || 8xx || E200 |
| 216 | default y | 216 | default y |
| 217 | 217 | ||
| 218 | config CONFIG_CHECK_CACHE_COHERENCY | 218 | config CHECK_CACHE_COHERENCY |
| 219 | bool | 219 | bool |
| 220 | 220 | ||
| 221 | endmenu | 221 | endmenu |
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index c2aaec5289dc..4100ddc52f02 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c | |||
| @@ -941,13 +941,6 @@ static const struct file_operations spufs_signal1_nosched_fops = { | |||
| 941 | .mmap = spufs_signal1_mmap, | 941 | .mmap = spufs_signal1_mmap, |
| 942 | }; | 942 | }; |
| 943 | 943 | ||
| 944 | static const struct file_operations spufs_signal1_nosched_fops = { | ||
| 945 | .open = spufs_signal1_open, | ||
| 946 | .release = spufs_signal1_release, | ||
| 947 | .write = spufs_signal1_write, | ||
| 948 | .mmap = spufs_signal1_mmap, | ||
| 949 | }; | ||
| 950 | |||
| 951 | static int spufs_signal2_open(struct inode *inode, struct file *file) | 944 | static int spufs_signal2_open(struct inode *inode, struct file *file) |
| 952 | { | 945 | { |
| 953 | struct spufs_inode_info *i = SPUFS_I(inode); | 946 | struct spufs_inode_info *i = SPUFS_I(inode); |
| @@ -1083,13 +1076,6 @@ static const struct file_operations spufs_signal2_nosched_fops = { | |||
| 1083 | .mmap = spufs_signal2_mmap, | 1076 | .mmap = spufs_signal2_mmap, |
| 1084 | }; | 1077 | }; |
| 1085 | 1078 | ||
| 1086 | static const struct file_operations spufs_signal2_nosched_fops = { | ||
| 1087 | .open = spufs_signal2_open, | ||
| 1088 | .release = spufs_signal2_release, | ||
| 1089 | .write = spufs_signal2_write, | ||
| 1090 | .mmap = spufs_signal2_mmap, | ||
| 1091 | }; | ||
| 1092 | |||
| 1093 | static void spufs_signal1_type_set(void *data, u64 val) | 1079 | static void spufs_signal1_type_set(void *data, u64 val) |
| 1094 | { | 1080 | { |
| 1095 | struct spu_context *ctx = data; | 1081 | struct spu_context *ctx = data; |
diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig index bec772674e40..2d12f77e46bc 100644 --- a/arch/powerpc/platforms/embedded6xx/Kconfig +++ b/arch/powerpc/platforms/embedded6xx/Kconfig | |||
| @@ -59,7 +59,7 @@ config MPC10X_BRIDGE | |||
| 59 | config MV64X60 | 59 | config MV64X60 |
| 60 | bool | 60 | bool |
| 61 | select PPC_INDIRECT_PCI | 61 | select PPC_INDIRECT_PCI |
| 62 | select CONFIG_CHECK_CACHE_COHERENCY | 62 | select CHECK_CACHE_COHERENCY |
| 63 | 63 | ||
| 64 | config MPC10X_OPENPIC | 64 | config MPC10X_OPENPIC |
| 65 | bool | 65 | bool |
diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c index 29bf83bfb1f0..8b18a1c40092 100644 --- a/arch/powerpc/platforms/pseries/firmware.c +++ b/arch/powerpc/platforms/pseries/firmware.c | |||
| @@ -66,24 +66,13 @@ firmware_features_table[FIRMWARE_MAX_FEATURES] = { | |||
| 66 | * device-tree/ibm,hypertas-functions. Ultimately this functionality may | 66 | * device-tree/ibm,hypertas-functions. Ultimately this functionality may |
| 67 | * be moved into prom.c prom_init(). | 67 | * be moved into prom.c prom_init(). |
| 68 | */ | 68 | */ |
| 69 | void __init fw_feature_init(void) | 69 | void __init fw_feature_init(const char *hypertas, unsigned long len) |
| 70 | { | 70 | { |
| 71 | struct device_node *dn; | 71 | const char *s; |
| 72 | const char *hypertas, *s; | 72 | int i; |
| 73 | int len, i; | ||
| 74 | 73 | ||
| 75 | DBG(" -> fw_feature_init()\n"); | 74 | DBG(" -> fw_feature_init()\n"); |
| 76 | 75 | ||
| 77 | dn = of_find_node_by_path("/rtas"); | ||
| 78 | if (dn == NULL) { | ||
| 79 | printk(KERN_ERR "WARNING! Cannot find RTAS in device-tree!\n"); | ||
| 80 | goto out; | ||
| 81 | } | ||
| 82 | |||
| 83 | hypertas = of_get_property(dn, "ibm,hypertas-functions", &len); | ||
| 84 | if (hypertas == NULL) | ||
| 85 | goto out; | ||
| 86 | |||
| 87 | for (s = hypertas; s < hypertas + len; s += strlen(s) + 1) { | 76 | for (s = hypertas; s < hypertas + len; s += strlen(s) + 1) { |
| 88 | for (i = 0; i < FIRMWARE_MAX_FEATURES; i++) { | 77 | for (i = 0; i < FIRMWARE_MAX_FEATURES; i++) { |
| 89 | /* check value against table of strings */ | 78 | /* check value against table of strings */ |
| @@ -98,7 +87,5 @@ void __init fw_feature_init(void) | |||
| 98 | } | 87 | } |
| 99 | } | 88 | } |
| 100 | 89 | ||
| 101 | out: | ||
| 102 | of_node_put(dn); | ||
| 103 | DBG(" <- fw_feature_init()\n"); | 90 | DBG(" <- fw_feature_init()\n"); |
| 104 | } | 91 | } |
diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h index 61e19f78b923..61136d019554 100644 --- a/arch/powerpc/platforms/pseries/pseries.h +++ b/arch/powerpc/platforms/pseries/pseries.h | |||
| @@ -10,7 +10,7 @@ | |||
| 10 | #ifndef _PSERIES_PSERIES_H | 10 | #ifndef _PSERIES_PSERIES_H |
| 11 | #define _PSERIES_PSERIES_H | 11 | #define _PSERIES_PSERIES_H |
| 12 | 12 | ||
| 13 | extern void __init fw_feature_init(void); | 13 | extern void __init fw_feature_init(const char *hypertas, unsigned long len); |
| 14 | 14 | ||
| 15 | struct pt_regs; | 15 | struct pt_regs; |
| 16 | 16 | ||
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 59e69f085cb4..f0b7146a110f 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
| @@ -320,8 +320,6 @@ static void __init pSeries_init_early(void) | |||
| 320 | { | 320 | { |
| 321 | DBG(" -> pSeries_init_early()\n"); | 321 | DBG(" -> pSeries_init_early()\n"); |
| 322 | 322 | ||
| 323 | fw_feature_init(); | ||
| 324 | |||
| 325 | if (firmware_has_feature(FW_FEATURE_LPAR)) | 323 | if (firmware_has_feature(FW_FEATURE_LPAR)) |
| 326 | find_udbg_vterm(); | 324 | find_udbg_vterm(); |
| 327 | 325 | ||
| @@ -343,14 +341,21 @@ static int __init pSeries_probe_hypertas(unsigned long node, | |||
| 343 | const char *uname, int depth, | 341 | const char *uname, int depth, |
| 344 | void *data) | 342 | void *data) |
| 345 | { | 343 | { |
| 344 | const char *hypertas; | ||
| 345 | unsigned long len; | ||
| 346 | |||
| 346 | if (depth != 1 || | 347 | if (depth != 1 || |
| 347 | (strcmp(uname, "rtas") != 0 && strcmp(uname, "rtas@0") != 0)) | 348 | (strcmp(uname, "rtas") != 0 && strcmp(uname, "rtas@0") != 0)) |
| 348 | return 0; | 349 | return 0; |
| 350 | |||
| 351 | hypertas = of_get_flat_dt_prop(node, "ibm,hypertas-functions", &len); | ||
| 352 | if (!hypertas) | ||
| 353 | return 1; | ||
| 349 | 354 | ||
| 350 | if (of_get_flat_dt_prop(node, "ibm,hypertas-functions", NULL) != NULL) | 355 | powerpc_firmware_features |= FW_FEATURE_LPAR; |
| 351 | powerpc_firmware_features |= FW_FEATURE_LPAR; | 356 | fw_feature_init(hypertas, len); |
| 352 | 357 | ||
| 353 | return 1; | 358 | return 1; |
| 354 | } | 359 | } |
| 355 | 360 | ||
| 356 | static int __init pSeries_probe(void) | 361 | static int __init pSeries_probe(void) |
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 75aad38179f0..74c64c0d3b71 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c | |||
| @@ -877,6 +877,8 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq, | |||
| 877 | 877 | ||
| 878 | if (hw == mpic->spurious_vec) | 878 | if (hw == mpic->spurious_vec) |
| 879 | return -EINVAL; | 879 | return -EINVAL; |
| 880 | if (mpic->protected && test_bit(hw, mpic->protected)) | ||
| 881 | return -EINVAL; | ||
| 880 | 882 | ||
| 881 | #ifdef CONFIG_SMP | 883 | #ifdef CONFIG_SMP |
| 882 | else if (hw >= mpic->ipi_vecs[0]) { | 884 | else if (hw >= mpic->ipi_vecs[0]) { |
| @@ -1034,6 +1036,25 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
| 1034 | if (node && of_get_property(node, "big-endian", NULL) != NULL) | 1036 | if (node && of_get_property(node, "big-endian", NULL) != NULL) |
| 1035 | mpic->flags |= MPIC_BIG_ENDIAN; | 1037 | mpic->flags |= MPIC_BIG_ENDIAN; |
| 1036 | 1038 | ||
| 1039 | /* Look for protected sources */ | ||
| 1040 | if (node) { | ||
| 1041 | unsigned int psize, bits, mapsize; | ||
| 1042 | const u32 *psrc = | ||
| 1043 | of_get_property(node, "protected-sources", &psize); | ||
| 1044 | if (psrc) { | ||
| 1045 | psize /= 4; | ||
| 1046 | bits = intvec_top + 1; | ||
| 1047 | mapsize = BITS_TO_LONGS(bits) * sizeof(unsigned long); | ||
| 1048 | mpic->protected = alloc_bootmem(mapsize); | ||
| 1049 | BUG_ON(mpic->protected == NULL); | ||
| 1050 | memset(mpic->protected, 0, mapsize); | ||
| 1051 | for (i = 0; i < psize; i++) { | ||
| 1052 | if (psrc[i] > intvec_top) | ||
| 1053 | continue; | ||
| 1054 | __set_bit(psrc[i], mpic->protected); | ||
| 1055 | } | ||
| 1056 | } | ||
| 1057 | } | ||
| 1037 | 1058 | ||
| 1038 | #ifdef CONFIG_MPIC_WEIRD | 1059 | #ifdef CONFIG_MPIC_WEIRD |
| 1039 | mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)]; | 1060 | mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)]; |
| @@ -1213,6 +1234,9 @@ void __init mpic_init(struct mpic *mpic) | |||
| 1213 | u32 vecpri = MPIC_VECPRI_MASK | i | | 1234 | u32 vecpri = MPIC_VECPRI_MASK | i | |
| 1214 | (8 << MPIC_VECPRI_PRIORITY_SHIFT); | 1235 | (8 << MPIC_VECPRI_PRIORITY_SHIFT); |
| 1215 | 1236 | ||
| 1237 | /* check if protected */ | ||
| 1238 | if (mpic->protected && test_bit(i, mpic->protected)) | ||
| 1239 | continue; | ||
| 1216 | /* init hw */ | 1240 | /* init hw */ |
| 1217 | mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri); | 1241 | mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri); |
| 1218 | mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), | 1242 | mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), |
| @@ -1407,6 +1431,14 @@ unsigned int mpic_get_one_irq(struct mpic *mpic) | |||
| 1407 | mpic_eoi(mpic); | 1431 | mpic_eoi(mpic); |
| 1408 | return NO_IRQ; | 1432 | return NO_IRQ; |
| 1409 | } | 1433 | } |
| 1434 | if (unlikely(mpic->protected && test_bit(src, mpic->protected))) { | ||
| 1435 | if (printk_ratelimit()) | ||
| 1436 | printk(KERN_WARNING "%s: Got protected source %d !\n", | ||
| 1437 | mpic->name, (int)src); | ||
| 1438 | mpic_eoi(mpic); | ||
| 1439 | return NO_IRQ; | ||
| 1440 | } | ||
| 1441 | |||
| 1410 | return irq_linear_revmap(mpic->irqhost, src); | 1442 | return irq_linear_revmap(mpic->irqhost, src); |
| 1411 | } | 1443 | } |
| 1412 | 1444 | ||
diff --git a/arch/powerpc/xmon/nonstdio.c b/arch/powerpc/xmon/nonstdio.c index 78765833f4c0..bfac84fbe780 100644 --- a/arch/powerpc/xmon/nonstdio.c +++ b/arch/powerpc/xmon/nonstdio.c | |||
| @@ -132,3 +132,8 @@ void xmon_printf(const char *format, ...) | |||
| 132 | va_end(args); | 132 | va_end(args); |
| 133 | xmon_write(xmon_outbuf, n); | 133 | xmon_write(xmon_outbuf, n); |
| 134 | } | 134 | } |
| 135 | |||
| 136 | void xmon_puts(const char *str) | ||
| 137 | { | ||
| 138 | xmon_write(str, strlen(str)); | ||
| 139 | } | ||
diff --git a/arch/powerpc/xmon/nonstdio.h b/arch/powerpc/xmon/nonstdio.h index 47cebbd2b1b1..23dd95f4599c 100644 --- a/arch/powerpc/xmon/nonstdio.h +++ b/arch/powerpc/xmon/nonstdio.h | |||
| @@ -5,10 +5,11 @@ | |||
| 5 | 5 | ||
| 6 | extern int xmon_putchar(int c); | 6 | extern int xmon_putchar(int c); |
| 7 | extern int xmon_getchar(void); | 7 | extern int xmon_getchar(void); |
| 8 | extern void xmon_puts(const char *); | ||
| 8 | extern char *xmon_gets(char *, int); | 9 | extern char *xmon_gets(char *, int); |
| 9 | extern void xmon_printf(const char *, ...); | 10 | extern void xmon_printf(const char *, ...); |
| 10 | extern void xmon_map_scc(void); | 11 | extern void xmon_map_scc(void); |
| 11 | extern int xmon_expect(const char *str, unsigned long timeout); | 12 | extern int xmon_expect(const char *str, unsigned long timeout); |
| 12 | extern int xmon_write(void *ptr, int nb); | 13 | extern int xmon_write(const void *ptr, int nb); |
| 13 | extern int xmon_readchar(void); | 14 | extern int xmon_readchar(void); |
| 14 | extern int xmon_read_poll(void); | 15 | extern int xmon_read_poll(void); |
diff --git a/arch/powerpc/xmon/start.c b/arch/powerpc/xmon/start.c index 712552c4f242..8864de2af382 100644 --- a/arch/powerpc/xmon/start.c +++ b/arch/powerpc/xmon/start.c | |||
| @@ -14,7 +14,7 @@ void xmon_map_scc(void) | |||
| 14 | { | 14 | { |
| 15 | } | 15 | } |
| 16 | 16 | ||
| 17 | int xmon_write(void *ptr, int nb) | 17 | int xmon_write(const void *ptr, int nb) |
| 18 | { | 18 | { |
| 19 | return udbg_write(ptr, nb); | 19 | return udbg_write(ptr, nb); |
| 20 | } | 20 | } |
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 669e6566ad70..121b04d165d1 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c | |||
| @@ -833,7 +833,7 @@ cmds(struct pt_regs *excp) | |||
| 833 | mdelay(2000); | 833 | mdelay(2000); |
| 834 | return cmd; | 834 | return cmd; |
| 835 | case '?': | 835 | case '?': |
| 836 | printf(help_string); | 836 | xmon_puts(help_string); |
| 837 | break; | 837 | break; |
| 838 | case 'b': | 838 | case 'b': |
| 839 | bpt_cmds(); | 839 | bpt_cmds(); |
diff --git a/arch/ppc/syslib/mv64x60.c b/arch/ppc/syslib/mv64x60.c index 032f4b7f4225..d212b1c418a9 100644 --- a/arch/ppc/syslib/mv64x60.c +++ b/arch/ppc/syslib/mv64x60.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include <linux/pci.h> | 14 | #include <linux/pci.h> |
| 15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
| 16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| 17 | #include <linux/mutex.h> | ||
| 17 | #include <linux/string.h> | 18 | #include <linux/string.h> |
| 18 | #include <linux/spinlock.h> | 19 | #include <linux/spinlock.h> |
| 19 | #include <linux/mv643xx.h> | 20 | #include <linux/mv643xx.h> |
| @@ -2359,7 +2360,7 @@ mv64460_chip_specific_init(struct mv64x60_handle *bh, | |||
| 2359 | /* Export the hotswap register via sysfs for enum event monitoring */ | 2360 | /* Export the hotswap register via sysfs for enum event monitoring */ |
| 2360 | #define VAL_LEN_MAX 11 /* 32-bit hex or dec stringified number + '\n' */ | 2361 | #define VAL_LEN_MAX 11 /* 32-bit hex or dec stringified number + '\n' */ |
| 2361 | 2362 | ||
| 2362 | DECLARE_MUTEX(mv64xxx_hs_lock); | 2363 | static DEFINE_MUTEX(mv64xxx_hs_lock); |
| 2363 | 2364 | ||
| 2364 | static ssize_t | 2365 | static ssize_t |
| 2365 | mv64xxx_hs_reg_read(struct kobject *kobj, char *buf, loff_t off, size_t count) | 2366 | mv64xxx_hs_reg_read(struct kobject *kobj, char *buf, loff_t off, size_t count) |
| @@ -2372,14 +2373,14 @@ mv64xxx_hs_reg_read(struct kobject *kobj, char *buf, loff_t off, size_t count) | |||
| 2372 | if (count < VAL_LEN_MAX) | 2373 | if (count < VAL_LEN_MAX) |
| 2373 | return -EINVAL; | 2374 | return -EINVAL; |
| 2374 | 2375 | ||
| 2375 | if (down_interruptible(&mv64xxx_hs_lock)) | 2376 | if (mutex_lock_interruptible(&mv64xxx_hs_lock)) |
| 2376 | return -ERESTARTSYS; | 2377 | return -ERESTARTSYS; |
| 2377 | save_exclude = mv64x60_pci_exclude_bridge; | 2378 | save_exclude = mv64x60_pci_exclude_bridge; |
| 2378 | mv64x60_pci_exclude_bridge = 0; | 2379 | mv64x60_pci_exclude_bridge = 0; |
| 2379 | early_read_config_dword(&sysfs_hose_a, 0, PCI_DEVFN(0, 0), | 2380 | early_read_config_dword(&sysfs_hose_a, 0, PCI_DEVFN(0, 0), |
| 2380 | MV64360_PCICFG_CPCI_HOTSWAP, &v); | 2381 | MV64360_PCICFG_CPCI_HOTSWAP, &v); |
| 2381 | mv64x60_pci_exclude_bridge = save_exclude; | 2382 | mv64x60_pci_exclude_bridge = save_exclude; |
| 2382 | up(&mv64xxx_hs_lock); | 2383 | mutex_unlock(&mv64xxx_hs_lock); |
| 2383 | 2384 | ||
| 2384 | return sprintf(buf, "0x%08x\n", v); | 2385 | return sprintf(buf, "0x%08x\n", v); |
| 2385 | } | 2386 | } |
| @@ -2396,14 +2397,14 @@ mv64xxx_hs_reg_write(struct kobject *kobj, char *buf, loff_t off, size_t count) | |||
| 2396 | return -EINVAL; | 2397 | return -EINVAL; |
| 2397 | 2398 | ||
| 2398 | if (sscanf(buf, "%i", &v) == 1) { | 2399 | if (sscanf(buf, "%i", &v) == 1) { |
| 2399 | if (down_interruptible(&mv64xxx_hs_lock)) | 2400 | if (mutex_lock_interruptible(&mv64xxx_hs_lock)) |
| 2400 | return -ERESTARTSYS; | 2401 | return -ERESTARTSYS; |
| 2401 | save_exclude = mv64x60_pci_exclude_bridge; | 2402 | save_exclude = mv64x60_pci_exclude_bridge; |
| 2402 | mv64x60_pci_exclude_bridge = 0; | 2403 | mv64x60_pci_exclude_bridge = 0; |
| 2403 | early_write_config_dword(&sysfs_hose_a, 0, PCI_DEVFN(0, 0), | 2404 | early_write_config_dword(&sysfs_hose_a, 0, PCI_DEVFN(0, 0), |
| 2404 | MV64360_PCICFG_CPCI_HOTSWAP, v); | 2405 | MV64360_PCICFG_CPCI_HOTSWAP, v); |
| 2405 | mv64x60_pci_exclude_bridge = save_exclude; | 2406 | mv64x60_pci_exclude_bridge = save_exclude; |
| 2406 | up(&mv64xxx_hs_lock); | 2407 | mutex_unlock(&mv64xxx_hs_lock); |
| 2407 | } | 2408 | } |
| 2408 | else | 2409 | else |
| 2409 | count = -EINVAL; | 2410 | count = -EINVAL; |
| @@ -2433,10 +2434,10 @@ mv64xxx_hs_reg_valid_show(struct device *dev, struct device_attribute *attr, | |||
| 2433 | pdev = container_of(dev, struct platform_device, dev); | 2434 | pdev = container_of(dev, struct platform_device, dev); |
| 2434 | pdp = (struct mv64xxx_pdata *)pdev->dev.platform_data; | 2435 | pdp = (struct mv64xxx_pdata *)pdev->dev.platform_data; |
| 2435 | 2436 | ||
| 2436 | if (down_interruptible(&mv64xxx_hs_lock)) | 2437 | if (mutex_lock_interruptible(&mv64xxx_hs_lock)) |
| 2437 | return -ERESTARTSYS; | 2438 | return -ERESTARTSYS; |
| 2438 | v = pdp->hs_reg_valid; | 2439 | v = pdp->hs_reg_valid; |
| 2439 | up(&mv64xxx_hs_lock); | 2440 | mutex_unlock(&mv64xxx_hs_lock); |
| 2440 | 2441 | ||
| 2441 | return sprintf(buf, "%i\n", v); | 2442 | return sprintf(buf, "%i\n", v); |
| 2442 | } | 2443 | } |
diff --git a/arch/x86_64/boot/compressed/Makefile b/arch/x86_64/boot/compressed/Makefile index c9f2da7496c1..877c0bdbbc67 100644 --- a/arch/x86_64/boot/compressed/Makefile +++ b/arch/x86_64/boot/compressed/Makefile | |||
| @@ -3,8 +3,6 @@ | |||
| 3 | # | 3 | # |
| 4 | # create a compressed vmlinux image from the original vmlinux | 4 | # create a compressed vmlinux image from the original vmlinux |
| 5 | # | 5 | # |
| 6 | # Note all the files here are compiled/linked as 32bit executables. | ||
| 7 | # | ||
| 8 | 6 | ||
| 9 | targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o | 7 | targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o |
| 10 | 8 | ||
diff --git a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S index 941c84baecc8..e89abcdbdde8 100644 --- a/arch/x86_64/kernel/head.S +++ b/arch/x86_64/kernel/head.S | |||
| @@ -25,7 +25,7 @@ | |||
| 25 | */ | 25 | */ |
| 26 | 26 | ||
| 27 | .text | 27 | .text |
| 28 | .section .bootstrap.text | 28 | .section .text.head |
| 29 | .code64 | 29 | .code64 |
| 30 | .globl startup_64 | 30 | .globl startup_64 |
| 31 | startup_64: | 31 | startup_64: |
| @@ -243,10 +243,16 @@ ENTRY(secondary_startup_64) | |||
| 243 | lretq | 243 | lretq |
| 244 | 244 | ||
| 245 | /* SMP bootup changes these two */ | 245 | /* SMP bootup changes these two */ |
| 246 | #ifndef CONFIG_HOTPLUG_CPU | ||
| 247 | .pushsection .init.data | ||
| 248 | #endif | ||
| 246 | .align 8 | 249 | .align 8 |
| 247 | .globl initial_code | 250 | .globl initial_code |
| 248 | initial_code: | 251 | initial_code: |
| 249 | .quad x86_64_start_kernel | 252 | .quad x86_64_start_kernel |
| 253 | #ifndef CONFIG_HOTPLUG_CPU | ||
| 254 | .popsection | ||
| 255 | #endif | ||
| 250 | .globl init_rsp | 256 | .globl init_rsp |
| 251 | init_rsp: | 257 | init_rsp: |
| 252 | .quad init_thread_union+THREAD_SIZE-8 | 258 | .quad init_thread_union+THREAD_SIZE-8 |
diff --git a/arch/x86_64/kernel/hpet.c b/arch/x86_64/kernel/hpet.c index 636f4f9fc6bb..e2d1b912e154 100644 --- a/arch/x86_64/kernel/hpet.c +++ b/arch/x86_64/kernel/hpet.c | |||
| @@ -133,7 +133,7 @@ struct clocksource clocksource_hpet = { | |||
| 133 | .vread = vread_hpet, | 133 | .vread = vread_hpet, |
| 134 | }; | 134 | }; |
| 135 | 135 | ||
| 136 | int hpet_arch_init(void) | 136 | int __init hpet_arch_init(void) |
| 137 | { | 137 | { |
| 138 | unsigned int id; | 138 | unsigned int id; |
| 139 | u64 tmp; | 139 | u64 tmp; |
diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c index d4a0d0ac9935..a30e004682e2 100644 --- a/arch/x86_64/kernel/kprobes.c +++ b/arch/x86_64/kernel/kprobes.c | |||
| @@ -39,9 +39,9 @@ | |||
| 39 | #include <linux/module.h> | 39 | #include <linux/module.h> |
| 40 | #include <linux/kdebug.h> | 40 | #include <linux/kdebug.h> |
| 41 | 41 | ||
| 42 | #include <asm/cacheflush.h> | ||
| 43 | #include <asm/pgtable.h> | 42 | #include <asm/pgtable.h> |
| 44 | #include <asm/uaccess.h> | 43 | #include <asm/uaccess.h> |
| 44 | #include <asm/alternative.h> | ||
| 45 | 45 | ||
| 46 | void jprobe_return_end(void); | 46 | void jprobe_return_end(void); |
| 47 | static void __kprobes arch_copy_kprobe(struct kprobe *p); | 47 | static void __kprobes arch_copy_kprobe(struct kprobe *p); |
| @@ -209,16 +209,12 @@ static void __kprobes arch_copy_kprobe(struct kprobe *p) | |||
| 209 | 209 | ||
| 210 | void __kprobes arch_arm_kprobe(struct kprobe *p) | 210 | void __kprobes arch_arm_kprobe(struct kprobe *p) |
| 211 | { | 211 | { |
| 212 | *p->addr = BREAKPOINT_INSTRUCTION; | 212 | text_poke(p->addr, ((unsigned char []){BREAKPOINT_INSTRUCTION}), 1); |
| 213 | flush_icache_range((unsigned long) p->addr, | ||
| 214 | (unsigned long) p->addr + sizeof(kprobe_opcode_t)); | ||
| 215 | } | 213 | } |
| 216 | 214 | ||
| 217 | void __kprobes arch_disarm_kprobe(struct kprobe *p) | 215 | void __kprobes arch_disarm_kprobe(struct kprobe *p) |
| 218 | { | 216 | { |
| 219 | *p->addr = p->opcode; | 217 | text_poke(p->addr, &p->opcode, 1); |
| 220 | flush_icache_range((unsigned long) p->addr, | ||
| 221 | (unsigned long) p->addr + sizeof(kprobe_opcode_t)); | ||
| 222 | } | 218 | } |
| 223 | 219 | ||
| 224 | void __kprobes arch_remove_kprobe(struct kprobe *p) | 220 | void __kprobes arch_remove_kprobe(struct kprobe *p) |
diff --git a/arch/x86_64/kernel/mce.c b/arch/x86_64/kernel/mce.c index 4d8450ee3635..a66d607f5b92 100644 --- a/arch/x86_64/kernel/mce.c +++ b/arch/x86_64/kernel/mce.c | |||
| @@ -667,6 +667,20 @@ static struct miscdevice mce_log_device = { | |||
| 667 | &mce_chrdev_ops, | 667 | &mce_chrdev_ops, |
| 668 | }; | 668 | }; |
| 669 | 669 | ||
| 670 | static unsigned long old_cr4 __initdata; | ||
| 671 | |||
| 672 | void __init stop_mce(void) | ||
| 673 | { | ||
| 674 | old_cr4 = read_cr4(); | ||
| 675 | clear_in_cr4(X86_CR4_MCE); | ||
| 676 | } | ||
| 677 | |||
| 678 | void __init restart_mce(void) | ||
| 679 | { | ||
| 680 | if (old_cr4 & X86_CR4_MCE) | ||
| 681 | set_in_cr4(X86_CR4_MCE); | ||
| 682 | } | ||
| 683 | |||
| 670 | /* | 684 | /* |
| 671 | * Old style boot options parsing. Only for compatibility. | 685 | * Old style boot options parsing. Only for compatibility. |
| 672 | */ | 686 | */ |
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c index edbbc59b7523..cb8ee9d02f86 100644 --- a/arch/x86_64/kernel/nmi.c +++ b/arch/x86_64/kernel/nmi.c | |||
| @@ -384,11 +384,14 @@ int __kprobes nmi_watchdog_tick(struct pt_regs * regs, unsigned reason) | |||
| 384 | return rc; | 384 | return rc; |
| 385 | } | 385 | } |
| 386 | 386 | ||
| 387 | static unsigned ignore_nmis; | ||
| 388 | |||
| 387 | asmlinkage __kprobes void do_nmi(struct pt_regs * regs, long error_code) | 389 | asmlinkage __kprobes void do_nmi(struct pt_regs * regs, long error_code) |
| 388 | { | 390 | { |
| 389 | nmi_enter(); | 391 | nmi_enter(); |
| 390 | add_pda(__nmi_count,1); | 392 | add_pda(__nmi_count,1); |
| 391 | default_do_nmi(regs); | 393 | if (!ignore_nmis) |
| 394 | default_do_nmi(regs); | ||
| 392 | nmi_exit(); | 395 | nmi_exit(); |
| 393 | } | 396 | } |
| 394 | 397 | ||
| @@ -401,6 +404,18 @@ int do_nmi_callback(struct pt_regs * regs, int cpu) | |||
| 401 | return 0; | 404 | return 0; |
| 402 | } | 405 | } |
| 403 | 406 | ||
| 407 | void stop_nmi(void) | ||
| 408 | { | ||
| 409 | acpi_nmi_disable(); | ||
| 410 | ignore_nmis++; | ||
| 411 | } | ||
| 412 | |||
| 413 | void restart_nmi(void) | ||
| 414 | { | ||
| 415 | ignore_nmis--; | ||
| 416 | acpi_nmi_enable(); | ||
| 417 | } | ||
| 418 | |||
| 404 | #ifdef CONFIG_SYSCTL | 419 | #ifdef CONFIG_SYSCTL |
| 405 | 420 | ||
| 406 | static int unknown_nmi_panic_callback(struct pt_regs *regs, int cpu) | 421 | static int unknown_nmi_panic_callback(struct pt_regs *regs, int cpu) |
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index 92fade4a62cf..e7ac629d4c46 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c | |||
| @@ -342,10 +342,10 @@ void __show_regs(struct pt_regs * regs) | |||
| 342 | rdmsrl(MSR_GS_BASE, gs); | 342 | rdmsrl(MSR_GS_BASE, gs); |
| 343 | rdmsrl(MSR_KERNEL_GS_BASE, shadowgs); | 343 | rdmsrl(MSR_KERNEL_GS_BASE, shadowgs); |
| 344 | 344 | ||
| 345 | asm("movq %%cr0, %0": "=r" (cr0)); | 345 | cr0 = read_cr0(); |
| 346 | asm("movq %%cr2, %0": "=r" (cr2)); | 346 | cr2 = read_cr2(); |
| 347 | asm("movq %%cr3, %0": "=r" (cr3)); | 347 | cr3 = read_cr3(); |
| 348 | asm("movq %%cr4, %0": "=r" (cr4)); | 348 | cr4 = read_cr4(); |
| 349 | 349 | ||
| 350 | printk("FS: %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n", | 350 | printk("FS: %016lx(%04x) GS:%016lx(%04x) knlGS:%016lx\n", |
| 351 | fs,fsindex,gs,gsindex,shadowgs); | 351 | fs,fsindex,gs,gsindex,shadowgs); |
diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index 6fa0a302e2aa..af838f6b0b7f 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c | |||
| @@ -608,6 +608,9 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) | |||
| 608 | else | 608 | else |
| 609 | num_cache_leaves = 3; | 609 | num_cache_leaves = 3; |
| 610 | 610 | ||
| 611 | if (c->x86 == 0xf || c->x86 == 0x10 || c->x86 == 0x11) | ||
| 612 | set_bit(X86_FEATURE_K8, &c->x86_capability); | ||
| 613 | |||
| 611 | /* RDTSC can be speculated around */ | 614 | /* RDTSC can be speculated around */ |
| 612 | clear_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability); | 615 | clear_bit(X86_FEATURE_SYNC_RDTSC, &c->x86_capability); |
| 613 | 616 | ||
diff --git a/arch/x86_64/kernel/signal.c b/arch/x86_64/kernel/signal.c index 4886afcd6287..739175b01e06 100644 --- a/arch/x86_64/kernel/signal.c +++ b/arch/x86_64/kernel/signal.c | |||
| @@ -487,7 +487,7 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) | |||
| 487 | void signal_fault(struct pt_regs *regs, void __user *frame, char *where) | 487 | void signal_fault(struct pt_regs *regs, void __user *frame, char *where) |
| 488 | { | 488 | { |
| 489 | struct task_struct *me = current; | 489 | struct task_struct *me = current; |
| 490 | if (exception_trace) | 490 | if (show_unhandled_signals && printk_ratelimit()) |
| 491 | printk("%s[%d] bad frame in %s frame:%p rip:%lx rsp:%lx orax:%lx\n", | 491 | printk("%s[%d] bad frame in %s frame:%p rip:%lx rsp:%lx orax:%lx\n", |
| 492 | me->comm,me->pid,where,frame,regs->rip,regs->rsp,regs->orig_rax); | 492 | me->comm,me->pid,where,frame,regs->rip,regs->rsp,regs->orig_rax); |
| 493 | 493 | ||
diff --git a/arch/x86_64/kernel/suspend.c b/arch/x86_64/kernel/suspend.c index 6a5a98f2a75c..ea83a9f91965 100644 --- a/arch/x86_64/kernel/suspend.c +++ b/arch/x86_64/kernel/suspend.c | |||
| @@ -55,11 +55,11 @@ void __save_processor_state(struct saved_context *ctxt) | |||
| 55 | * control registers | 55 | * control registers |
| 56 | */ | 56 | */ |
| 57 | rdmsrl(MSR_EFER, ctxt->efer); | 57 | rdmsrl(MSR_EFER, ctxt->efer); |
| 58 | asm volatile ("movq %%cr0, %0" : "=r" (ctxt->cr0)); | 58 | ctxt->cr0 = read_cr0(); |
| 59 | asm volatile ("movq %%cr2, %0" : "=r" (ctxt->cr2)); | 59 | ctxt->cr2 = read_cr2(); |
| 60 | asm volatile ("movq %%cr3, %0" : "=r" (ctxt->cr3)); | 60 | ctxt->cr3 = read_cr3(); |
| 61 | asm volatile ("movq %%cr4, %0" : "=r" (ctxt->cr4)); | 61 | ctxt->cr4 = read_cr4(); |
| 62 | asm volatile ("movq %%cr8, %0" : "=r" (ctxt->cr8)); | 62 | ctxt->cr8 = read_cr8(); |
| 63 | } | 63 | } |
| 64 | 64 | ||
| 65 | void save_processor_state(void) | 65 | void save_processor_state(void) |
| @@ -81,11 +81,11 @@ void __restore_processor_state(struct saved_context *ctxt) | |||
| 81 | * control registers | 81 | * control registers |
| 82 | */ | 82 | */ |
| 83 | wrmsrl(MSR_EFER, ctxt->efer); | 83 | wrmsrl(MSR_EFER, ctxt->efer); |
| 84 | asm volatile ("movq %0, %%cr8" :: "r" (ctxt->cr8)); | 84 | write_cr8(ctxt->cr8); |
| 85 | asm volatile ("movq %0, %%cr4" :: "r" (ctxt->cr4)); | 85 | write_cr4(ctxt->cr4); |
| 86 | asm volatile ("movq %0, %%cr3" :: "r" (ctxt->cr3)); | 86 | write_cr3(ctxt->cr3); |
| 87 | asm volatile ("movq %0, %%cr2" :: "r" (ctxt->cr2)); | 87 | write_cr2(ctxt->cr2); |
| 88 | asm volatile ("movq %0, %%cr0" :: "r" (ctxt->cr0)); | 88 | write_cr0(ctxt->cr0); |
| 89 | 89 | ||
| 90 | /* | 90 | /* |
| 91 | * now restore the descriptor tables to their proper values | 91 | * now restore the descriptor tables to their proper values |
diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index 8713ad4a4db1..03888420775d 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c | |||
| @@ -584,7 +584,8 @@ static void __kprobes do_trap(int trapnr, int signr, char *str, | |||
| 584 | tsk->thread.error_code = error_code; | 584 | tsk->thread.error_code = error_code; |
| 585 | tsk->thread.trap_no = trapnr; | 585 | tsk->thread.trap_no = trapnr; |
| 586 | 586 | ||
| 587 | if (exception_trace && unhandled_signal(tsk, signr)) | 587 | if (show_unhandled_signals && unhandled_signal(tsk, signr) && |
| 588 | printk_ratelimit()) | ||
| 588 | printk(KERN_INFO | 589 | printk(KERN_INFO |
| 589 | "%s[%d] trap %s rip:%lx rsp:%lx error:%lx\n", | 590 | "%s[%d] trap %s rip:%lx rsp:%lx error:%lx\n", |
| 590 | tsk->comm, tsk->pid, str, | 591 | tsk->comm, tsk->pid, str, |
| @@ -688,7 +689,8 @@ asmlinkage void __kprobes do_general_protection(struct pt_regs * regs, | |||
| 688 | tsk->thread.error_code = error_code; | 689 | tsk->thread.error_code = error_code; |
| 689 | tsk->thread.trap_no = 13; | 690 | tsk->thread.trap_no = 13; |
| 690 | 691 | ||
| 691 | if (exception_trace && unhandled_signal(tsk, SIGSEGV)) | 692 | if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) && |
| 693 | printk_ratelimit()) | ||
| 692 | printk(KERN_INFO | 694 | printk(KERN_INFO |
| 693 | "%s[%d] general protection rip:%lx rsp:%lx error:%lx\n", | 695 | "%s[%d] general protection rip:%lx rsp:%lx error:%lx\n", |
| 694 | tsk->comm, tsk->pid, | 696 | tsk->comm, tsk->pid, |
diff --git a/arch/x86_64/kernel/vmlinux.lds.S b/arch/x86_64/kernel/vmlinux.lds.S index e7a5eb6cd785..ba8ea97abd21 100644 --- a/arch/x86_64/kernel/vmlinux.lds.S +++ b/arch/x86_64/kernel/vmlinux.lds.S | |||
| @@ -28,7 +28,7 @@ SECTIONS | |||
| 28 | _text = .; /* Text and read-only data */ | 28 | _text = .; /* Text and read-only data */ |
| 29 | .text : AT(ADDR(.text) - LOAD_OFFSET) { | 29 | .text : AT(ADDR(.text) - LOAD_OFFSET) { |
| 30 | /* First the code that has to be first for bootstrapping */ | 30 | /* First the code that has to be first for bootstrapping */ |
| 31 | *(.bootstrap.text) | 31 | *(.text.head) |
| 32 | _stext = .; | 32 | _stext = .; |
| 33 | /* Then the rest */ | 33 | /* Then the rest */ |
| 34 | TEXT_TEXT | 34 | TEXT_TEXT |
diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c index 2074bddd4f04..327c9f2fa626 100644 --- a/arch/x86_64/mm/fault.c +++ b/arch/x86_64/mm/fault.c | |||
| @@ -159,7 +159,7 @@ void dump_pagetable(unsigned long address) | |||
| 159 | pmd_t *pmd; | 159 | pmd_t *pmd; |
| 160 | pte_t *pte; | 160 | pte_t *pte; |
| 161 | 161 | ||
| 162 | asm("movq %%cr3,%0" : "=r" (pgd)); | 162 | pgd = (pgd_t *)read_cr3(); |
| 163 | 163 | ||
| 164 | pgd = __va((unsigned long)pgd & PHYSICAL_PAGE_MASK); | 164 | pgd = __va((unsigned long)pgd & PHYSICAL_PAGE_MASK); |
| 165 | pgd += pgd_index(address); | 165 | pgd += pgd_index(address); |
| @@ -221,16 +221,6 @@ static int is_errata93(struct pt_regs *regs, unsigned long address) | |||
| 221 | return 0; | 221 | return 0; |
| 222 | } | 222 | } |
| 223 | 223 | ||
| 224 | int unhandled_signal(struct task_struct *tsk, int sig) | ||
| 225 | { | ||
| 226 | if (is_init(tsk)) | ||
| 227 | return 1; | ||
| 228 | if (tsk->ptrace & PT_PTRACED) | ||
| 229 | return 0; | ||
| 230 | return (tsk->sighand->action[sig-1].sa.sa_handler == SIG_IGN) || | ||
| 231 | (tsk->sighand->action[sig-1].sa.sa_handler == SIG_DFL); | ||
| 232 | } | ||
| 233 | |||
| 234 | static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs, | 224 | static noinline void pgtable_bad(unsigned long address, struct pt_regs *regs, |
| 235 | unsigned long error_code) | 225 | unsigned long error_code) |
| 236 | { | 226 | { |
| @@ -302,7 +292,7 @@ static int vmalloc_fault(unsigned long address) | |||
| 302 | } | 292 | } |
| 303 | 293 | ||
| 304 | static int page_fault_trace; | 294 | static int page_fault_trace; |
| 305 | int exception_trace = 1; | 295 | int show_unhandled_signals = 1; |
| 306 | 296 | ||
| 307 | /* | 297 | /* |
| 308 | * This routine handles page faults. It determines the address, | 298 | * This routine handles page faults. It determines the address, |
| @@ -326,7 +316,7 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, | |||
| 326 | prefetchw(&mm->mmap_sem); | 316 | prefetchw(&mm->mmap_sem); |
| 327 | 317 | ||
| 328 | /* get the address */ | 318 | /* get the address */ |
| 329 | __asm__("movq %%cr2,%0":"=r" (address)); | 319 | address = read_cr2(); |
| 330 | 320 | ||
| 331 | info.si_code = SEGV_MAPERR; | 321 | info.si_code = SEGV_MAPERR; |
| 332 | 322 | ||
| @@ -494,7 +484,8 @@ bad_area_nosemaphore: | |||
| 494 | (address >> 32)) | 484 | (address >> 32)) |
| 495 | return; | 485 | return; |
| 496 | 486 | ||
| 497 | if (exception_trace && unhandled_signal(tsk, SIGSEGV)) { | 487 | if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) && |
| 488 | printk_ratelimit()) { | ||
| 498 | printk( | 489 | printk( |
| 499 | "%s%s[%d]: segfault at %016lx rip %016lx rsp %016lx error %lx\n", | 490 | "%s%s[%d]: segfault at %016lx rip %016lx rsp %016lx error %lx\n", |
| 500 | tsk->pid > 1 ? KERN_INFO : KERN_EMERG, | 491 | tsk->pid > 1 ? KERN_INFO : KERN_EMERG, |
diff --git a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c index 381c2ecd407e..38f5d6368006 100644 --- a/arch/x86_64/mm/init.c +++ b/arch/x86_64/mm/init.c | |||
| @@ -383,7 +383,7 @@ void __meminit init_memory_mapping(unsigned long start, unsigned long end) | |||
| 383 | } | 383 | } |
| 384 | 384 | ||
| 385 | if (!after_bootmem) | 385 | if (!after_bootmem) |
| 386 | asm volatile("movq %%cr4,%0" : "=r" (mmu_cr4_features)); | 386 | mmu_cr4_features = read_cr4(); |
| 387 | __flush_tlb_all(); | 387 | __flush_tlb_all(); |
| 388 | } | 388 | } |
| 389 | 389 | ||
| @@ -600,16 +600,6 @@ void mark_rodata_ro(void) | |||
| 600 | { | 600 | { |
| 601 | unsigned long start = (unsigned long)_stext, end; | 601 | unsigned long start = (unsigned long)_stext, end; |
| 602 | 602 | ||
| 603 | #ifdef CONFIG_HOTPLUG_CPU | ||
| 604 | /* It must still be possible to apply SMP alternatives. */ | ||
| 605 | if (num_possible_cpus() > 1) | ||
| 606 | start = (unsigned long)_etext; | ||
| 607 | #endif | ||
| 608 | |||
| 609 | #ifdef CONFIG_KPROBES | ||
| 610 | start = (unsigned long)__start_rodata; | ||
| 611 | #endif | ||
| 612 | |||
| 613 | end = (unsigned long)__end_rodata; | 603 | end = (unsigned long)__end_rodata; |
| 614 | start = (start + PAGE_SIZE - 1) & PAGE_MASK; | 604 | start = (start + PAGE_SIZE - 1) & PAGE_MASK; |
| 615 | end &= PAGE_MASK; | 605 | end &= PAGE_MASK; |
| @@ -697,39 +687,6 @@ int kern_addr_valid(unsigned long addr) | |||
| 697 | return pfn_valid(pte_pfn(*pte)); | 687 | return pfn_valid(pte_pfn(*pte)); |
| 698 | } | 688 | } |
| 699 | 689 | ||
| 700 | #ifdef CONFIG_SYSCTL | ||
| 701 | #include <linux/sysctl.h> | ||
| 702 | |||
| 703 | static ctl_table debug_table2[] = { | ||
| 704 | { | ||
| 705 | .ctl_name = 99, | ||
| 706 | .procname = "exception-trace", | ||
| 707 | .data = &exception_trace, | ||
| 708 | .maxlen = sizeof(int), | ||
| 709 | .mode = 0644, | ||
| 710 | .proc_handler = proc_dointvec | ||
| 711 | }, | ||
| 712 | {} | ||
| 713 | }; | ||
| 714 | |||
| 715 | static ctl_table debug_root_table2[] = { | ||
| 716 | { | ||
| 717 | .ctl_name = CTL_DEBUG, | ||
| 718 | .procname = "debug", | ||
| 719 | .mode = 0555, | ||
| 720 | .child = debug_table2 | ||
| 721 | }, | ||
| 722 | {} | ||
| 723 | }; | ||
| 724 | |||
| 725 | static __init int x8664_sysctl_init(void) | ||
| 726 | { | ||
| 727 | register_sysctl_table(debug_root_table2); | ||
| 728 | return 0; | ||
| 729 | } | ||
| 730 | __initcall(x8664_sysctl_init); | ||
| 731 | #endif | ||
| 732 | |||
| 733 | /* A pseudo VMA to allow ptrace access for the vsyscall page. This only | 690 | /* A pseudo VMA to allow ptrace access for the vsyscall page. This only |
| 734 | covers the 64bit vsyscall page now. 32bit has a real VMA now and does | 691 | covers the 64bit vsyscall page now. 32bit has a real VMA now and does |
| 735 | not need special handling anymore. */ | 692 | not need special handling anymore. */ |
| @@ -767,7 +724,7 @@ int in_gate_area_no_task(unsigned long addr) | |||
| 767 | return (addr >= VSYSCALL_START) && (addr < VSYSCALL_END); | 724 | return (addr >= VSYSCALL_START) && (addr < VSYSCALL_END); |
| 768 | } | 725 | } |
| 769 | 726 | ||
| 770 | void *alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size) | 727 | void * __init alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size) |
| 771 | { | 728 | { |
| 772 | return __alloc_bootmem_core(pgdat->bdata, size, | 729 | return __alloc_bootmem_core(pgdat->bdata, size, |
| 773 | SMP_CACHE_BYTES, (4UL*1024*1024*1024), 0); | 730 | SMP_CACHE_BYTES, (4UL*1024*1024*1024), 0); |
diff --git a/arch/x86_64/mm/pageattr.c b/arch/x86_64/mm/pageattr.c index 36377b6b8efe..7e161c698af4 100644 --- a/arch/x86_64/mm/pageattr.c +++ b/arch/x86_64/mm/pageattr.c | |||
| @@ -13,7 +13,7 @@ | |||
| 13 | #include <asm/tlbflush.h> | 13 | #include <asm/tlbflush.h> |
| 14 | #include <asm/io.h> | 14 | #include <asm/io.h> |
| 15 | 15 | ||
| 16 | static inline pte_t *lookup_address(unsigned long address) | 16 | pte_t *lookup_address(unsigned long address) |
| 17 | { | 17 | { |
| 18 | pgd_t *pgd = pgd_offset_k(address); | 18 | pgd_t *pgd = pgd_offset_k(address); |
| 19 | pud_t *pud; | 19 | pud_t *pud; |
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 139f41f033d8..408b45168aba 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
| @@ -2,16 +2,12 @@ | |||
| 2 | # ACPI Configuration | 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 | depends on !X86_NUMAQ | 7 | depends on !X86_NUMAQ |
| 7 | depends on !X86_VISWS | 8 | depends on !X86_VISWS |
| 8 | depends on !IA64_HP_SIM | 9 | depends on !IA64_HP_SIM |
| 9 | depends on IA64 || X86 | 10 | depends on IA64 || X86 |
| 10 | depends on PM | ||
| 11 | |||
| 12 | config ACPI | ||
| 13 | bool "ACPI Support" | ||
| 14 | depends on IA64 || X86 | ||
| 15 | depends on PCI | 11 | depends on PCI |
| 16 | depends on PM | 12 | depends on PM |
| 17 | select PNP | 13 | select PNP |
| @@ -49,7 +45,6 @@ if ACPI | |||
| 49 | config ACPI_SLEEP | 45 | config ACPI_SLEEP |
| 50 | bool "Sleep States" | 46 | bool "Sleep States" |
| 51 | depends on X86 && (!SMP || SUSPEND_SMP) | 47 | depends on X86 && (!SMP || SUSPEND_SMP) |
| 52 | depends on PM | ||
| 53 | default y | 48 | default y |
| 54 | ---help--- | 49 | ---help--- |
| 55 | This option adds support for ACPI suspend states. | 50 | This option adds support for ACPI suspend states. |
| @@ -82,7 +77,6 @@ config ACPI_SLEEP_PROC_SLEEP | |||
| 82 | 77 | ||
| 83 | config ACPI_PROCFS | 78 | config ACPI_PROCFS |
| 84 | bool "Procfs interface (deprecated)" | 79 | bool "Procfs interface (deprecated)" |
| 85 | depends on ACPI | ||
| 86 | default y | 80 | default y |
| 87 | ---help--- | 81 | ---help--- |
| 88 | The Procfs interface for ACPI is made optional for backward compatibility. | 82 | The Procfs interface for ACPI is made optional for backward compatibility. |
| @@ -124,7 +118,7 @@ config ACPI_BUTTON | |||
| 124 | 118 | ||
| 125 | config ACPI_VIDEO | 119 | config ACPI_VIDEO |
| 126 | tristate "Video" | 120 | tristate "Video" |
| 127 | depends on X86 && BACKLIGHT_CLASS_DEVICE | 121 | depends on X86 && BACKLIGHT_CLASS_DEVICE && VIDEO_OUTPUT_CONTROL |
| 128 | help | 122 | help |
| 129 | This driver implement the ACPI Extensions For Display Adapters | 123 | This driver implement the ACPI Extensions For Display Adapters |
| 130 | for integrated graphics devices on motherboard, as specified in | 124 | for integrated graphics devices on motherboard, as specified in |
| @@ -280,6 +274,14 @@ config ACPI_DEBUG | |||
| 280 | of verbosity. Saying Y enables these statements. This will increase | 274 | of verbosity. Saying Y enables these statements. This will increase |
| 281 | your kernel size by around 50K. | 275 | your kernel size by around 50K. |
| 282 | 276 | ||
| 277 | config ACPI_DEBUG_FUNC_TRACE | ||
| 278 | bool "Additionally enable ACPI function tracing" | ||
| 279 | default n | ||
| 280 | depends on ACPI_DEBUG | ||
| 281 | help | ||
| 282 | ACPI Debug Statements slow down ACPI processing. Function trace | ||
| 283 | is about half of the penalty and is rarely useful. | ||
| 284 | |||
| 283 | config ACPI_EC | 285 | config ACPI_EC |
| 284 | bool | 286 | bool |
| 285 | default y | 287 | default y |
| @@ -330,7 +332,6 @@ config ACPI_CONTAINER | |||
| 330 | 332 | ||
| 331 | config ACPI_HOTPLUG_MEMORY | 333 | config ACPI_HOTPLUG_MEMORY |
| 332 | tristate "Memory Hotplug" | 334 | tristate "Memory Hotplug" |
| 333 | depends on ACPI | ||
| 334 | depends on MEMORY_HOTPLUG | 335 | depends on MEMORY_HOTPLUG |
| 335 | default n | 336 | default n |
| 336 | help | 337 | help |
| @@ -359,5 +360,3 @@ config ACPI_SBS | |||
| 359 | to today's ACPI "Control Method" battery. | 360 | to today's ACPI "Control Method" battery. |
| 360 | 361 | ||
| 361 | endif # ACPI | 362 | endif # ACPI |
| 362 | |||
| 363 | endmenu | ||
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index e64c76c8b726..cad932de383d 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c | |||
| @@ -43,21 +43,30 @@ | |||
| 43 | #define ACPI_BATTERY_CLASS "battery" | 43 | #define ACPI_BATTERY_CLASS "battery" |
| 44 | #define ACPI_BATTERY_HID "PNP0C0A" | 44 | #define ACPI_BATTERY_HID "PNP0C0A" |
| 45 | #define ACPI_BATTERY_DEVICE_NAME "Battery" | 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 | #define ACPI_BATTERY_NOTIFY_STATUS 0x80 | 46 | #define ACPI_BATTERY_NOTIFY_STATUS 0x80 |
| 50 | #define ACPI_BATTERY_NOTIFY_INFO 0x81 | 47 | #define ACPI_BATTERY_NOTIFY_INFO 0x81 |
| 51 | #define ACPI_BATTERY_UNITS_WATTS "mW" | 48 | #define ACPI_BATTERY_UNITS_WATTS "mW" |
| 52 | #define ACPI_BATTERY_UNITS_AMPS "mA" | 49 | #define ACPI_BATTERY_UNITS_AMPS "mA" |
| 53 | 50 | ||
| 54 | #define _COMPONENT ACPI_BATTERY_COMPONENT | 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 | ACPI_MODULE_NAME("battery"); | 59 | ACPI_MODULE_NAME("battery"); |
| 56 | 60 | ||
| 57 | MODULE_AUTHOR("Paul Diefenbaugh"); | 61 | MODULE_AUTHOR("Paul Diefenbaugh"); |
| 58 | MODULE_DESCRIPTION("ACPI Battery Driver"); | 62 | MODULE_DESCRIPTION("ACPI Battery Driver"); |
| 59 | MODULE_LICENSE("GPL"); | 63 | MODULE_LICENSE("GPL"); |
| 60 | 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); | ||
| 69 | |||
| 61 | extern struct proc_dir_entry *acpi_lock_battery_dir(void); | 70 | extern struct proc_dir_entry *acpi_lock_battery_dir(void); |
| 62 | extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); | 71 | extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); |
| 63 | 72 | ||
| @@ -76,7 +85,7 @@ static struct acpi_driver acpi_battery_driver = { | |||
| 76 | }, | 85 | }, |
| 77 | }; | 86 | }; |
| 78 | 87 | ||
| 79 | struct acpi_battery_status { | 88 | struct acpi_battery_state { |
| 80 | acpi_integer state; | 89 | acpi_integer state; |
| 81 | acpi_integer present_rate; | 90 | acpi_integer present_rate; |
| 82 | acpi_integer remaining_capacity; | 91 | acpi_integer remaining_capacity; |
| @@ -99,33 +108,111 @@ struct acpi_battery_info { | |||
| 99 | acpi_string oem_info; | 108 | acpi_string oem_info; |
| 100 | }; | 109 | }; |
| 101 | 110 | ||
| 102 | struct acpi_battery_flags { | 111 | enum acpi_battery_files{ |
| 103 | u8 present:1; /* Bay occupied? */ | 112 | ACPI_BATTERY_INFO = 0, |
| 104 | u8 power_unit:1; /* 0=watts, 1=apms */ | 113 | ACPI_BATTERY_STATE, |
| 105 | u8 alarm:1; /* _BTP present? */ | 114 | ACPI_BATTERY_ALARM, |
| 106 | u8 reserved:5; | 115 | ACPI_BATTERY_NUMFILES, |
| 107 | }; | 116 | }; |
| 108 | 117 | ||
| 109 | struct acpi_battery_trips { | 118 | struct acpi_battery_flags { |
| 110 | unsigned long warning; | 119 | u8 battery_present_prev; |
| 111 | unsigned long low; | 120 | u8 alarm_present; |
| 121 | u8 init_update; | ||
| 122 | u8 update[ACPI_BATTERY_NUMFILES]; | ||
| 123 | u8 power_unit; | ||
| 112 | }; | 124 | }; |
| 113 | 125 | ||
| 114 | struct acpi_battery { | 126 | struct acpi_battery { |
| 115 | struct acpi_device * device; | 127 | struct mutex mutex; |
| 128 | struct acpi_device *device; | ||
| 116 | struct acpi_battery_flags flags; | 129 | struct acpi_battery_flags flags; |
| 117 | struct acpi_battery_trips trips; | 130 | struct acpi_buffer bif_data; |
| 131 | struct acpi_buffer bst_data; | ||
| 118 | unsigned long alarm; | 132 | unsigned long alarm; |
| 119 | struct acpi_battery_info *info; | 133 | unsigned long update_time[ACPI_BATTERY_NUMFILES]; |
| 120 | }; | 134 | }; |
| 121 | 135 | ||
| 136 | inline int acpi_battery_present(struct acpi_battery *battery) | ||
| 137 | { | ||
| 138 | return battery->device->status.battery_present; | ||
| 139 | } | ||
| 140 | inline char *acpi_battery_power_units(struct acpi_battery *battery) | ||
| 141 | { | ||
| 142 | if (battery->flags.power_unit) | ||
| 143 | return ACPI_BATTERY_UNITS_AMPS; | ||
| 144 | else | ||
| 145 | return ACPI_BATTERY_UNITS_WATTS; | ||
| 146 | } | ||
| 147 | |||
| 148 | inline acpi_handle acpi_battery_handle(struct acpi_battery *battery) | ||
| 149 | { | ||
| 150 | return battery->device->handle; | ||
| 151 | } | ||
| 152 | |||
| 122 | /* -------------------------------------------------------------------------- | 153 | /* -------------------------------------------------------------------------- |
| 123 | Battery Management | 154 | Battery Management |
| 124 | -------------------------------------------------------------------------- */ | 155 | -------------------------------------------------------------------------- */ |
| 125 | 156 | ||
| 126 | static int | 157 | static void acpi_battery_check_result(struct acpi_battery *battery, int result) |
| 127 | acpi_battery_get_info(struct acpi_battery *battery, | 158 | { |
| 128 | struct acpi_battery_info **bif) | 159 | if (!battery) |
| 160 | return; | ||
| 161 | |||
| 162 | if (result) { | ||
| 163 | battery->flags.init_update = 1; | ||
| 164 | } | ||
| 165 | } | ||
| 166 | |||
| 167 | static int acpi_battery_extract_package(struct acpi_battery *battery, | ||
| 168 | union acpi_object *package, | ||
| 169 | struct acpi_buffer *format, | ||
| 170 | struct acpi_buffer *data, | ||
| 171 | char *package_name) | ||
| 172 | { | ||
| 173 | acpi_status status = AE_OK; | ||
| 174 | struct acpi_buffer data_null = { 0, NULL }; | ||
| 175 | |||
| 176 | status = acpi_extract_package(package, format, &data_null); | ||
| 177 | if (status != AE_BUFFER_OVERFLOW) { | ||
| 178 | ACPI_EXCEPTION((AE_INFO, status, "Extracting size %s", | ||
| 179 | package_name)); | ||
| 180 | return -ENODEV; | ||
| 181 | } | ||
| 182 | |||
| 183 | if (data_null.length != data->length) { | ||
| 184 | kfree(data->pointer); | ||
| 185 | data->pointer = kzalloc(data_null.length, GFP_KERNEL); | ||
| 186 | if (!data->pointer) { | ||
| 187 | ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, "kzalloc()")); | ||
| 188 | return -ENOMEM; | ||
| 189 | } | ||
| 190 | data->length = data_null.length; | ||
| 191 | } | ||
| 192 | |||
| 193 | status = acpi_extract_package(package, format, data); | ||
| 194 | if (ACPI_FAILURE(status)) { | ||
| 195 | ACPI_EXCEPTION((AE_INFO, status, "Extracting %s", | ||
| 196 | package_name)); | ||
| 197 | return -ENODEV; | ||
| 198 | } | ||
| 199 | |||
| 200 | return 0; | ||
| 201 | } | ||
| 202 | |||
| 203 | static int acpi_battery_get_status(struct acpi_battery *battery) | ||
| 204 | { | ||
| 205 | int result = 0; | ||
| 206 | |||
| 207 | result = acpi_bus_get_status(battery->device); | ||
| 208 | if (result) { | ||
| 209 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Evaluating _STA")); | ||
| 210 | return -ENODEV; | ||
| 211 | } | ||
| 212 | return result; | ||
| 213 | } | ||
| 214 | |||
| 215 | static int acpi_battery_get_info(struct acpi_battery *battery) | ||
| 129 | { | 216 | { |
| 130 | int result = 0; | 217 | int result = 0; |
| 131 | acpi_status status = 0; | 218 | acpi_status status = 0; |
| @@ -133,16 +220,20 @@ acpi_battery_get_info(struct acpi_battery *battery, | |||
| 133 | struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BIF), | 220 | struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BIF), |
| 134 | ACPI_BATTERY_FORMAT_BIF | 221 | ACPI_BATTERY_FORMAT_BIF |
| 135 | }; | 222 | }; |
| 136 | struct acpi_buffer data = { 0, NULL }; | ||
| 137 | union acpi_object *package = NULL; | 223 | union acpi_object *package = NULL; |
| 224 | struct acpi_buffer *data = NULL; | ||
| 225 | struct acpi_battery_info *bif = NULL; | ||
| 138 | 226 | ||
| 227 | battery->update_time[ACPI_BATTERY_INFO] = get_seconds(); | ||
| 139 | 228 | ||
| 140 | if (!battery || !bif) | 229 | if (!acpi_battery_present(battery)) |
| 141 | return -EINVAL; | 230 | return 0; |
| 142 | 231 | ||
| 143 | /* Evalute _BIF */ | 232 | /* Evaluate _BIF */ |
| 144 | 233 | ||
| 145 | status = acpi_evaluate_object(battery->device->handle, "_BIF", NULL, &buffer); | 234 | status = |
| 235 | acpi_evaluate_object(acpi_battery_handle(battery), "_BIF", NULL, | ||
| 236 | &buffer); | ||
| 146 | if (ACPI_FAILURE(status)) { | 237 | if (ACPI_FAILURE(status)) { |
| 147 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF")); | 238 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF")); |
| 148 | return -ENODEV; | 239 | return -ENODEV; |
| @@ -150,41 +241,29 @@ acpi_battery_get_info(struct acpi_battery *battery, | |||
| 150 | 241 | ||
| 151 | package = buffer.pointer; | 242 | package = buffer.pointer; |
| 152 | 243 | ||
| 153 | /* Extract Package Data */ | 244 | data = &battery->bif_data; |
| 154 | |||
| 155 | status = acpi_extract_package(package, &format, &data); | ||
| 156 | if (status != AE_BUFFER_OVERFLOW) { | ||
| 157 | ACPI_EXCEPTION((AE_INFO, status, "Extracting _BIF")); | ||
| 158 | result = -ENODEV; | ||
| 159 | goto end; | ||
| 160 | } | ||
| 161 | 245 | ||
| 162 | data.pointer = kzalloc(data.length, GFP_KERNEL); | 246 | /* Extract Package Data */ |
| 163 | if (!data.pointer) { | ||
| 164 | result = -ENOMEM; | ||
| 165 | goto end; | ||
| 166 | } | ||
| 167 | 247 | ||
| 168 | status = acpi_extract_package(package, &format, &data); | 248 | result = |
| 169 | if (ACPI_FAILURE(status)) { | 249 | acpi_battery_extract_package(battery, package, &format, data, |
| 170 | ACPI_EXCEPTION((AE_INFO, status, "Extracting _BIF")); | 250 | "_BIF"); |
| 171 | kfree(data.pointer); | 251 | if (result) |
| 172 | result = -ENODEV; | ||
| 173 | goto end; | 252 | goto end; |
| 174 | } | ||
| 175 | 253 | ||
| 176 | end: | 254 | end: |
| 255 | |||
| 177 | kfree(buffer.pointer); | 256 | kfree(buffer.pointer); |
| 178 | 257 | ||
| 179 | if (!result) | 258 | if (!result) { |
| 180 | (*bif) = data.pointer; | 259 | bif = data->pointer; |
| 260 | battery->flags.power_unit = bif->power_unit; | ||
| 261 | } | ||
| 181 | 262 | ||
| 182 | return result; | 263 | return result; |
| 183 | } | 264 | } |
| 184 | 265 | ||
| 185 | static int | 266 | static int acpi_battery_get_state(struct acpi_battery *battery) |
| 186 | acpi_battery_get_status(struct acpi_battery *battery, | ||
| 187 | struct acpi_battery_status **bst) | ||
| 188 | { | 267 | { |
| 189 | int result = 0; | 268 | int result = 0; |
| 190 | acpi_status status = 0; | 269 | acpi_status status = 0; |
| @@ -192,16 +271,19 @@ acpi_battery_get_status(struct acpi_battery *battery, | |||
| 192 | struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BST), | 271 | struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BST), |
| 193 | ACPI_BATTERY_FORMAT_BST | 272 | ACPI_BATTERY_FORMAT_BST |
| 194 | }; | 273 | }; |
| 195 | struct acpi_buffer data = { 0, NULL }; | ||
| 196 | union acpi_object *package = NULL; | 274 | union acpi_object *package = NULL; |
| 275 | struct acpi_buffer *data = NULL; | ||
| 197 | 276 | ||
| 277 | battery->update_time[ACPI_BATTERY_STATE] = get_seconds(); | ||
| 198 | 278 | ||
| 199 | if (!battery || !bst) | 279 | if (!acpi_battery_present(battery)) |
| 200 | return -EINVAL; | 280 | return 0; |
| 201 | 281 | ||
| 202 | /* Evalute _BST */ | 282 | /* Evaluate _BST */ |
| 203 | 283 | ||
| 204 | status = acpi_evaluate_object(battery->device->handle, "_BST", NULL, &buffer); | 284 | status = |
| 285 | acpi_evaluate_object(acpi_battery_handle(battery), "_BST", NULL, | ||
| 286 | &buffer); | ||
| 205 | if (ACPI_FAILURE(status)) { | 287 | if (ACPI_FAILURE(status)) { |
| 206 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST")); | 288 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST")); |
| 207 | return -ENODEV; | 289 | return -ENODEV; |
| @@ -209,55 +291,49 @@ acpi_battery_get_status(struct acpi_battery *battery, | |||
| 209 | 291 | ||
| 210 | package = buffer.pointer; | 292 | package = buffer.pointer; |
| 211 | 293 | ||
| 212 | /* Extract Package Data */ | 294 | data = &battery->bst_data; |
| 213 | |||
| 214 | status = acpi_extract_package(package, &format, &data); | ||
| 215 | if (status != AE_BUFFER_OVERFLOW) { | ||
| 216 | ACPI_EXCEPTION((AE_INFO, status, "Extracting _BST")); | ||
| 217 | result = -ENODEV; | ||
| 218 | goto end; | ||
| 219 | } | ||
| 220 | 295 | ||
| 221 | data.pointer = kzalloc(data.length, GFP_KERNEL); | 296 | /* Extract Package Data */ |
| 222 | if (!data.pointer) { | ||
| 223 | result = -ENOMEM; | ||
| 224 | goto end; | ||
| 225 | } | ||
| 226 | 297 | ||
| 227 | status = acpi_extract_package(package, &format, &data); | 298 | result = |
| 228 | if (ACPI_FAILURE(status)) { | 299 | acpi_battery_extract_package(battery, package, &format, data, |
| 229 | ACPI_EXCEPTION((AE_INFO, status, "Extracting _BST")); | 300 | "_BST"); |
| 230 | kfree(data.pointer); | 301 | if (result) |
| 231 | result = -ENODEV; | ||
| 232 | goto end; | 302 | goto end; |
| 233 | } | ||
| 234 | 303 | ||
| 235 | end: | 304 | end: |
| 236 | kfree(buffer.pointer); | 305 | kfree(buffer.pointer); |
| 237 | 306 | ||
| 238 | if (!result) | ||
| 239 | (*bst) = data.pointer; | ||
| 240 | |||
| 241 | return result; | 307 | return result; |
| 242 | } | 308 | } |
| 243 | 309 | ||
| 244 | static int | 310 | static int acpi_battery_get_alarm(struct acpi_battery *battery) |
| 245 | acpi_battery_set_alarm(struct acpi_battery *battery, unsigned long alarm) | 311 | { |
| 312 | battery->update_time[ACPI_BATTERY_ALARM] = get_seconds(); | ||
| 313 | |||
| 314 | return 0; | ||
| 315 | } | ||
| 316 | |||
| 317 | static int acpi_battery_set_alarm(struct acpi_battery *battery, | ||
| 318 | unsigned long alarm) | ||
| 246 | { | 319 | { |
| 247 | acpi_status status = 0; | 320 | acpi_status status = 0; |
| 248 | union acpi_object arg0 = { ACPI_TYPE_INTEGER }; | 321 | union acpi_object arg0 = { ACPI_TYPE_INTEGER }; |
| 249 | struct acpi_object_list arg_list = { 1, &arg0 }; | 322 | struct acpi_object_list arg_list = { 1, &arg0 }; |
| 250 | 323 | ||
| 324 | battery->update_time[ACPI_BATTERY_ALARM] = get_seconds(); | ||
| 251 | 325 | ||
| 252 | if (!battery) | 326 | if (!acpi_battery_present(battery)) |
| 253 | return -EINVAL; | 327 | return -ENODEV; |
| 254 | 328 | ||
| 255 | if (!battery->flags.alarm) | 329 | if (!battery->flags.alarm_present) |
| 256 | return -ENODEV; | 330 | return -ENODEV; |
| 257 | 331 | ||
| 258 | arg0.integer.value = alarm; | 332 | arg0.integer.value = alarm; |
| 259 | 333 | ||
| 260 | status = acpi_evaluate_object(battery->device->handle, "_BTP", &arg_list, NULL); | 334 | status = |
| 335 | acpi_evaluate_object(acpi_battery_handle(battery), "_BTP", | ||
| 336 | &arg_list, NULL); | ||
| 261 | if (ACPI_FAILURE(status)) | 337 | if (ACPI_FAILURE(status)) |
| 262 | return -ENODEV; | 338 | return -ENODEV; |
| 263 | 339 | ||
| @@ -268,65 +344,114 @@ acpi_battery_set_alarm(struct acpi_battery *battery, unsigned long alarm) | |||
| 268 | return 0; | 344 | return 0; |
| 269 | } | 345 | } |
| 270 | 346 | ||
| 271 | static int acpi_battery_check(struct acpi_battery *battery) | 347 | static int acpi_battery_init_alarm(struct acpi_battery *battery) |
| 272 | { | 348 | { |
| 273 | int result = 0; | 349 | int result = 0; |
| 274 | acpi_status status = AE_OK; | 350 | acpi_status status = AE_OK; |
| 275 | acpi_handle handle = NULL; | 351 | acpi_handle handle = NULL; |
| 276 | struct acpi_device *device = NULL; | 352 | struct acpi_battery_info *bif = battery->bif_data.pointer; |
| 277 | struct acpi_battery_info *bif = NULL; | 353 | unsigned long alarm = battery->alarm; |
| 278 | 354 | ||
| 355 | /* See if alarms are supported, and if so, set default */ | ||
| 279 | 356 | ||
| 280 | if (!battery) | 357 | status = acpi_get_handle(acpi_battery_handle(battery), "_BTP", &handle); |
| 281 | return -EINVAL; | 358 | if (ACPI_SUCCESS(status)) { |
| 282 | 359 | battery->flags.alarm_present = 1; | |
| 283 | device = battery->device; | 360 | if (!alarm && bif) { |
| 361 | alarm = bif->design_capacity_warning; | ||
| 362 | } | ||
| 363 | result = acpi_battery_set_alarm(battery, alarm); | ||
| 364 | if (result) | ||
| 365 | goto end; | ||
| 366 | } else { | ||
| 367 | battery->flags.alarm_present = 0; | ||
| 368 | } | ||
| 284 | 369 | ||
| 285 | result = acpi_bus_get_status(device); | 370 | end: |
| 286 | if (result) | ||
| 287 | return result; | ||
| 288 | 371 | ||
| 289 | /* Insertion? */ | 372 | return result; |
| 373 | } | ||
| 290 | 374 | ||
| 291 | if (!battery->flags.present && device->status.battery_present) { | 375 | static int acpi_battery_init_update(struct acpi_battery *battery) |
| 376 | { | ||
| 377 | int result = 0; | ||
| 292 | 378 | ||
| 293 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery inserted\n")); | 379 | result = acpi_battery_get_status(battery); |
| 380 | if (result) | ||
| 381 | return result; | ||
| 294 | 382 | ||
| 295 | /* Evalute _BIF to get certain static information */ | 383 | battery->flags.battery_present_prev = acpi_battery_present(battery); |
| 296 | 384 | ||
| 297 | result = acpi_battery_get_info(battery, &bif); | 385 | if (acpi_battery_present(battery)) { |
| 386 | result = acpi_battery_get_info(battery); | ||
| 387 | if (result) | ||
| 388 | return result; | ||
| 389 | result = acpi_battery_get_state(battery); | ||
| 298 | if (result) | 390 | if (result) |
| 299 | return result; | 391 | return result; |
| 300 | 392 | ||
| 301 | battery->flags.power_unit = bif->power_unit; | 393 | acpi_battery_init_alarm(battery); |
| 302 | battery->trips.warning = bif->design_capacity_warning; | 394 | } |
| 303 | battery->trips.low = bif->design_capacity_low; | 395 | |
| 304 | kfree(bif); | 396 | return result; |
| 397 | } | ||
| 305 | 398 | ||
| 306 | /* See if alarms are supported, and if so, set default */ | 399 | static int acpi_battery_update(struct acpi_battery *battery, |
| 400 | int update, int *update_result_ptr) | ||
| 401 | { | ||
| 402 | int result = 0; | ||
| 403 | int update_result = ACPI_BATTERY_NONE_UPDATE; | ||
| 404 | |||
| 405 | if (!acpi_battery_present(battery)) { | ||
| 406 | update = 1; | ||
| 407 | } | ||
| 307 | 408 | ||
| 308 | status = acpi_get_handle(battery->device->handle, "_BTP", &handle); | 409 | if (battery->flags.init_update) { |
| 309 | if (ACPI_SUCCESS(status)) { | 410 | result = acpi_battery_init_update(battery); |
| 310 | battery->flags.alarm = 1; | 411 | if (result) |
| 311 | acpi_battery_set_alarm(battery, battery->trips.warning); | 412 | goto end; |
| 413 | update_result = ACPI_BATTERY_INIT_UPDATE; | ||
| 414 | } else if (update) { | ||
| 415 | result = acpi_battery_get_status(battery); | ||
| 416 | if (result) | ||
| 417 | goto end; | ||
| 418 | if ((!battery->flags.battery_present_prev & acpi_battery_present(battery)) | ||
| 419 | || (battery->flags.battery_present_prev & !acpi_battery_present(battery))) { | ||
| 420 | result = acpi_battery_init_update(battery); | ||
| 421 | if (result) | ||
| 422 | goto end; | ||
| 423 | update_result = ACPI_BATTERY_INIT_UPDATE; | ||
| 424 | } else { | ||
| 425 | update_result = ACPI_BATTERY_EASY_UPDATE; | ||
| 312 | } | 426 | } |
| 313 | } | 427 | } |
| 314 | 428 | ||
| 315 | /* Removal? */ | 429 | end: |
| 316 | 430 | ||
| 317 | else if (battery->flags.present && !device->status.battery_present) { | 431 | battery->flags.init_update = (result != 0); |
| 318 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery removed\n")); | ||
| 319 | } | ||
| 320 | 432 | ||
| 321 | battery->flags.present = device->status.battery_present; | 433 | *update_result_ptr = update_result; |
| 322 | 434 | ||
| 323 | return result; | 435 | return result; |
| 324 | } | 436 | } |
| 325 | 437 | ||
| 326 | static void acpi_battery_check_present(struct acpi_battery *battery) | 438 | static void acpi_battery_notify_update(struct acpi_battery *battery) |
| 327 | { | 439 | { |
| 328 | if (!battery->flags.present) { | 440 | acpi_battery_get_status(battery); |
| 329 | acpi_battery_check(battery); | 441 | |
| 442 | if (battery->flags.init_update) { | ||
| 443 | return; | ||
| 444 | } | ||
| 445 | |||
| 446 | if ((!battery->flags.battery_present_prev & | ||
| 447 | acpi_battery_present(battery)) || | ||
| 448 | (battery->flags.battery_present_prev & | ||
| 449 | !acpi_battery_present(battery))) { | ||
| 450 | battery->flags.init_update = 1; | ||
| 451 | } else { | ||
| 452 | battery->flags.update[ACPI_BATTERY_INFO] = 1; | ||
| 453 | battery->flags.update[ACPI_BATTERY_STATE] = 1; | ||
| 454 | battery->flags.update[ACPI_BATTERY_ALARM] = 1; | ||
| 330 | } | 455 | } |
| 331 | } | 456 | } |
| 332 | 457 | ||
| @@ -335,37 +460,33 @@ static void acpi_battery_check_present(struct acpi_battery *battery) | |||
| 335 | -------------------------------------------------------------------------- */ | 460 | -------------------------------------------------------------------------- */ |
| 336 | 461 | ||
| 337 | static struct proc_dir_entry *acpi_battery_dir; | 462 | static struct proc_dir_entry *acpi_battery_dir; |
| 338 | static int acpi_battery_read_info(struct seq_file *seq, void *offset) | 463 | |
| 464 | static int acpi_battery_print_info(struct seq_file *seq, int result) | ||
| 339 | { | 465 | { |
| 340 | int result = 0; | ||
| 341 | struct acpi_battery *battery = seq->private; | 466 | struct acpi_battery *battery = seq->private; |
| 342 | struct acpi_battery_info *bif = NULL; | 467 | struct acpi_battery_info *bif = NULL; |
| 343 | char *units = "?"; | 468 | char *units = "?"; |
| 344 | 469 | ||
| 345 | 470 | if (result) | |
| 346 | if (!battery) | ||
| 347 | goto end; | 471 | goto end; |
| 348 | 472 | ||
| 349 | acpi_battery_check_present(battery); | 473 | if (acpi_battery_present(battery)) |
| 350 | |||
| 351 | if (battery->flags.present) | ||
| 352 | seq_printf(seq, "present: yes\n"); | 474 | seq_printf(seq, "present: yes\n"); |
| 353 | else { | 475 | else { |
| 354 | seq_printf(seq, "present: no\n"); | 476 | seq_printf(seq, "present: no\n"); |
| 355 | goto end; | 477 | goto end; |
| 356 | } | 478 | } |
| 357 | 479 | ||
| 358 | /* Battery Info (_BIF) */ | 480 | bif = battery->bif_data.pointer; |
| 359 | 481 | if (!bif) { | |
| 360 | result = acpi_battery_get_info(battery, &bif); | 482 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, "BIF buffer is NULL")); |
| 361 | if (result || !bif) { | 483 | result = -ENODEV; |
| 362 | seq_printf(seq, "ERROR: Unable to read battery information\n"); | ||
| 363 | goto end; | 484 | goto end; |
| 364 | } | 485 | } |
| 365 | 486 | ||
| 366 | units = | 487 | /* Battery Units */ |
| 367 | bif-> | 488 | |
| 368 | power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS; | 489 | units = acpi_battery_power_units(battery); |
| 369 | 490 | ||
| 370 | if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN) | 491 | if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN) |
| 371 | seq_printf(seq, "design capacity: unknown\n"); | 492 | seq_printf(seq, "design capacity: unknown\n"); |
| @@ -396,7 +517,6 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset) | |||
| 396 | else | 517 | else |
| 397 | seq_printf(seq, "design voltage: %d mV\n", | 518 | seq_printf(seq, "design voltage: %d mV\n", |
| 398 | (u32) bif->design_voltage); | 519 | (u32) bif->design_voltage); |
| 399 | |||
| 400 | seq_printf(seq, "design capacity warning: %d %sh\n", | 520 | seq_printf(seq, "design capacity warning: %d %sh\n", |
| 401 | (u32) bif->design_capacity_warning, units); | 521 | (u32) bif->design_capacity_warning, units); |
| 402 | seq_printf(seq, "design capacity low: %d %sh\n", | 522 | seq_printf(seq, "design capacity low: %d %sh\n", |
| @@ -411,50 +531,40 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset) | |||
| 411 | seq_printf(seq, "OEM info: %s\n", bif->oem_info); | 531 | seq_printf(seq, "OEM info: %s\n", bif->oem_info); |
| 412 | 532 | ||
| 413 | end: | 533 | end: |
| 414 | kfree(bif); | ||
| 415 | 534 | ||
| 416 | return 0; | 535 | if (result) |
| 417 | } | 536 | seq_printf(seq, "ERROR: Unable to read battery info\n"); |
| 418 | 537 | ||
| 419 | static int acpi_battery_info_open_fs(struct inode *inode, struct file *file) | 538 | return result; |
| 420 | { | ||
| 421 | return single_open(file, acpi_battery_read_info, PDE(inode)->data); | ||
| 422 | } | 539 | } |
| 423 | 540 | ||
| 424 | static int acpi_battery_read_state(struct seq_file *seq, void *offset) | 541 | static int acpi_battery_print_state(struct seq_file *seq, int result) |
| 425 | { | 542 | { |
| 426 | int result = 0; | ||
| 427 | struct acpi_battery *battery = seq->private; | 543 | struct acpi_battery *battery = seq->private; |
| 428 | struct acpi_battery_status *bst = NULL; | 544 | struct acpi_battery_state *bst = NULL; |
| 429 | char *units = "?"; | 545 | char *units = "?"; |
| 430 | 546 | ||
| 431 | 547 | if (result) | |
| 432 | if (!battery) | ||
| 433 | goto end; | 548 | goto end; |
| 434 | 549 | ||
| 435 | acpi_battery_check_present(battery); | 550 | if (acpi_battery_present(battery)) |
| 436 | |||
| 437 | if (battery->flags.present) | ||
| 438 | seq_printf(seq, "present: yes\n"); | 551 | seq_printf(seq, "present: yes\n"); |
| 439 | else { | 552 | else { |
| 440 | seq_printf(seq, "present: no\n"); | 553 | seq_printf(seq, "present: no\n"); |
| 441 | goto end; | 554 | goto end; |
| 442 | } | 555 | } |
| 443 | 556 | ||
| 444 | /* Battery Units */ | 557 | bst = battery->bst_data.pointer; |
| 445 | 558 | if (!bst) { | |
| 446 | units = | 559 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, "BST buffer is NULL")); |
| 447 | battery->flags. | 560 | result = -ENODEV; |
| 448 | power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS; | ||
| 449 | |||
| 450 | /* Battery Status (_BST) */ | ||
| 451 | |||
| 452 | result = acpi_battery_get_status(battery, &bst); | ||
| 453 | if (result || !bst) { | ||
| 454 | seq_printf(seq, "ERROR: Unable to read battery status\n"); | ||
| 455 | goto end; | 561 | goto end; |
| 456 | } | 562 | } |
| 457 | 563 | ||
| 564 | /* Battery Units */ | ||
| 565 | |||
| 566 | units = acpi_battery_power_units(battery); | ||
| 567 | |||
| 458 | if (!(bst->state & 0x04)) | 568 | if (!(bst->state & 0x04)) |
| 459 | seq_printf(seq, "capacity state: ok\n"); | 569 | seq_printf(seq, "capacity state: ok\n"); |
| 460 | else | 570 | else |
| @@ -490,48 +600,43 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset) | |||
| 490 | (u32) bst->present_voltage); | 600 | (u32) bst->present_voltage); |
| 491 | 601 | ||
| 492 | end: | 602 | end: |
| 493 | kfree(bst); | ||
| 494 | 603 | ||
| 495 | return 0; | 604 | if (result) { |
| 496 | } | 605 | seq_printf(seq, "ERROR: Unable to read battery state\n"); |
| 606 | } | ||
| 497 | 607 | ||
| 498 | static int acpi_battery_state_open_fs(struct inode *inode, struct file *file) | 608 | return result; |
| 499 | { | ||
| 500 | return single_open(file, acpi_battery_read_state, PDE(inode)->data); | ||
| 501 | } | 609 | } |
| 502 | 610 | ||
| 503 | static int acpi_battery_read_alarm(struct seq_file *seq, void *offset) | 611 | static int acpi_battery_print_alarm(struct seq_file *seq, int result) |
| 504 | { | 612 | { |
| 505 | struct acpi_battery *battery = seq->private; | 613 | struct acpi_battery *battery = seq->private; |
| 506 | char *units = "?"; | 614 | char *units = "?"; |
| 507 | 615 | ||
| 508 | 616 | if (result) | |
| 509 | if (!battery) | ||
| 510 | goto end; | 617 | goto end; |
| 511 | 618 | ||
| 512 | acpi_battery_check_present(battery); | 619 | if (!acpi_battery_present(battery)) { |
| 513 | |||
| 514 | if (!battery->flags.present) { | ||
| 515 | seq_printf(seq, "present: no\n"); | 620 | seq_printf(seq, "present: no\n"); |
| 516 | goto end; | 621 | goto end; |
| 517 | } | 622 | } |
| 518 | 623 | ||
| 519 | /* Battery Units */ | 624 | /* Battery Units */ |
| 520 | 625 | ||
| 521 | units = | 626 | units = acpi_battery_power_units(battery); |
| 522 | battery->flags. | ||
| 523 | power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS; | ||
| 524 | |||
| 525 | /* Battery Alarm */ | ||
| 526 | 627 | ||
| 527 | seq_printf(seq, "alarm: "); | 628 | seq_printf(seq, "alarm: "); |
| 528 | if (!battery->alarm) | 629 | if (!battery->alarm) |
| 529 | seq_printf(seq, "unsupported\n"); | 630 | seq_printf(seq, "unsupported\n"); |
| 530 | else | 631 | else |
| 531 | seq_printf(seq, "%d %sh\n", (u32) battery->alarm, units); | 632 | seq_printf(seq, "%lu %sh\n", battery->alarm, units); |
| 532 | 633 | ||
| 533 | end: | 634 | end: |
| 534 | return 0; | 635 | |
| 636 | if (result) | ||
| 637 | seq_printf(seq, "ERROR: Unable to read battery alarm\n"); | ||
| 638 | |||
| 639 | return result; | ||
| 535 | } | 640 | } |
| 536 | 641 | ||
| 537 | static ssize_t | 642 | static ssize_t |
| @@ -543,27 +648,113 @@ acpi_battery_write_alarm(struct file *file, | |||
| 543 | char alarm_string[12] = { '\0' }; | 648 | char alarm_string[12] = { '\0' }; |
| 544 | struct seq_file *m = file->private_data; | 649 | struct seq_file *m = file->private_data; |
| 545 | struct acpi_battery *battery = m->private; | 650 | struct acpi_battery *battery = m->private; |
| 546 | 651 | int update_result = ACPI_BATTERY_NONE_UPDATE; | |
| 547 | 652 | ||
| 548 | if (!battery || (count > sizeof(alarm_string) - 1)) | 653 | if (!battery || (count > sizeof(alarm_string) - 1)) |
| 549 | return -EINVAL; | 654 | return -EINVAL; |
| 550 | 655 | ||
| 551 | acpi_battery_check_present(battery); | 656 | mutex_lock(&battery->mutex); |
| 552 | 657 | ||
| 553 | if (!battery->flags.present) | 658 | result = acpi_battery_update(battery, 1, &update_result); |
| 554 | return -ENODEV; | 659 | if (result) { |
| 660 | result = -ENODEV; | ||
| 661 | goto end; | ||
| 662 | } | ||
| 663 | |||
| 664 | if (!acpi_battery_present(battery)) { | ||
| 665 | result = -ENODEV; | ||
| 666 | goto end; | ||
| 667 | } | ||
| 555 | 668 | ||
| 556 | if (copy_from_user(alarm_string, buffer, count)) | 669 | if (copy_from_user(alarm_string, buffer, count)) { |
| 557 | return -EFAULT; | 670 | result = -EFAULT; |
| 671 | goto end; | ||
| 672 | } | ||
| 558 | 673 | ||
| 559 | alarm_string[count] = '\0'; | 674 | alarm_string[count] = '\0'; |
| 560 | 675 | ||
| 561 | result = acpi_battery_set_alarm(battery, | 676 | result = acpi_battery_set_alarm(battery, |
| 562 | simple_strtoul(alarm_string, NULL, 0)); | 677 | simple_strtoul(alarm_string, NULL, 0)); |
| 563 | if (result) | 678 | if (result) |
| 564 | return result; | 679 | goto end; |
| 680 | |||
| 681 | end: | ||
| 565 | 682 | ||
| 566 | return count; | 683 | acpi_battery_check_result(battery, result); |
| 684 | |||
| 685 | if (!result) | ||
| 686 | result = count; | ||
| 687 | |||
| 688 | mutex_unlock(&battery->mutex); | ||
| 689 | |||
| 690 | return result; | ||
| 691 | } | ||
| 692 | |||
| 693 | typedef int(*print_func)(struct seq_file *seq, int result); | ||
| 694 | typedef int(*get_func)(struct acpi_battery *battery); | ||
| 695 | |||
| 696 | static struct acpi_read_mux { | ||
| 697 | print_func print; | ||
| 698 | get_func get; | ||
| 699 | } acpi_read_funcs[ACPI_BATTERY_NUMFILES] = { | ||
| 700 | {.get = acpi_battery_get_info, .print = acpi_battery_print_info}, | ||
| 701 | {.get = acpi_battery_get_state, .print = acpi_battery_print_state}, | ||
| 702 | {.get = acpi_battery_get_alarm, .print = acpi_battery_print_alarm}, | ||
| 703 | }; | ||
| 704 | |||
| 705 | static int acpi_battery_read(int fid, struct seq_file *seq) | ||
| 706 | { | ||
| 707 | struct acpi_battery *battery = seq->private; | ||
| 708 | int result = 0; | ||
| 709 | int update_result = ACPI_BATTERY_NONE_UPDATE; | ||
| 710 | int update = 0; | ||
| 711 | |||
| 712 | mutex_lock(&battery->mutex); | ||
| 713 | |||
| 714 | update = (get_seconds() - battery->update_time[fid] >= update_time); | ||
| 715 | update = (update | battery->flags.update[fid]); | ||
| 716 | |||
| 717 | result = acpi_battery_update(battery, update, &update_result); | ||
| 718 | if (result) | ||
| 719 | goto end; | ||
| 720 | |||
| 721 | if (update_result == ACPI_BATTERY_EASY_UPDATE) { | ||
| 722 | result = acpi_read_funcs[fid].get(battery); | ||
| 723 | if (result) | ||
| 724 | goto end; | ||
| 725 | } | ||
| 726 | |||
| 727 | end: | ||
| 728 | result = acpi_read_funcs[fid].print(seq, result); | ||
| 729 | acpi_battery_check_result(battery, result); | ||
| 730 | battery->flags.update[fid] = result; | ||
| 731 | mutex_unlock(&battery->mutex); | ||
| 732 | return result; | ||
| 733 | } | ||
| 734 | |||
| 735 | static int acpi_battery_read_info(struct seq_file *seq, void *offset) | ||
| 736 | { | ||
| 737 | return acpi_battery_read(ACPI_BATTERY_INFO, seq); | ||
| 738 | } | ||
| 739 | |||
| 740 | static int acpi_battery_read_state(struct seq_file *seq, void *offset) | ||
| 741 | { | ||
| 742 | return acpi_battery_read(ACPI_BATTERY_STATE, seq); | ||
| 743 | } | ||
| 744 | |||
| 745 | static int acpi_battery_read_alarm(struct seq_file *seq, void *offset) | ||
| 746 | { | ||
| 747 | return acpi_battery_read(ACPI_BATTERY_ALARM, seq); | ||
| 748 | } | ||
| 749 | |||
| 750 | static int acpi_battery_info_open_fs(struct inode *inode, struct file *file) | ||
| 751 | { | ||
| 752 | return single_open(file, acpi_battery_read_info, PDE(inode)->data); | ||
| 753 | } | ||
| 754 | |||
| 755 | static int acpi_battery_state_open_fs(struct inode *inode, struct file *file) | ||
| 756 | { | ||
| 757 | return single_open(file, acpi_battery_read_state, PDE(inode)->data); | ||
| 567 | } | 758 | } |
| 568 | 759 | ||
| 569 | static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file) | 760 | static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file) |
| @@ -571,35 +762,51 @@ static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file) | |||
| 571 | return single_open(file, acpi_battery_read_alarm, PDE(inode)->data); | 762 | return single_open(file, acpi_battery_read_alarm, PDE(inode)->data); |
| 572 | } | 763 | } |
| 573 | 764 | ||
| 574 | static const struct file_operations acpi_battery_info_ops = { | 765 | static struct battery_file { |
| 766 | struct file_operations ops; | ||
| 767 | mode_t mode; | ||
| 768 | char *name; | ||
| 769 | } acpi_battery_file[] = { | ||
| 770 | { | ||
| 771 | .name = "info", | ||
| 772 | .mode = S_IRUGO, | ||
| 773 | .ops = { | ||
| 575 | .open = acpi_battery_info_open_fs, | 774 | .open = acpi_battery_info_open_fs, |
| 576 | .read = seq_read, | 775 | .read = seq_read, |
| 577 | .llseek = seq_lseek, | 776 | .llseek = seq_lseek, |
| 578 | .release = single_release, | 777 | .release = single_release, |
| 579 | .owner = THIS_MODULE, | 778 | .owner = THIS_MODULE, |
| 580 | }; | 779 | }, |
| 581 | 780 | }, | |
| 582 | static const struct file_operations acpi_battery_state_ops = { | 781 | { |
| 782 | .name = "state", | ||
| 783 | .mode = S_IRUGO, | ||
| 784 | .ops = { | ||
| 583 | .open = acpi_battery_state_open_fs, | 785 | .open = acpi_battery_state_open_fs, |
| 584 | .read = seq_read, | 786 | .read = seq_read, |
| 585 | .llseek = seq_lseek, | 787 | .llseek = seq_lseek, |
| 586 | .release = single_release, | 788 | .release = single_release, |
| 587 | .owner = THIS_MODULE, | 789 | .owner = THIS_MODULE, |
| 588 | }; | 790 | }, |
| 589 | 791 | }, | |
| 590 | static const struct file_operations acpi_battery_alarm_ops = { | 792 | { |
| 793 | .name = "alarm", | ||
| 794 | .mode = S_IFREG | S_IRUGO | S_IWUSR, | ||
| 795 | .ops = { | ||
| 591 | .open = acpi_battery_alarm_open_fs, | 796 | .open = acpi_battery_alarm_open_fs, |
| 592 | .read = seq_read, | 797 | .read = seq_read, |
| 593 | .write = acpi_battery_write_alarm, | 798 | .write = acpi_battery_write_alarm, |
| 594 | .llseek = seq_lseek, | 799 | .llseek = seq_lseek, |
| 595 | .release = single_release, | 800 | .release = single_release, |
| 596 | .owner = THIS_MODULE, | 801 | .owner = THIS_MODULE, |
| 802 | }, | ||
| 803 | }, | ||
| 597 | }; | 804 | }; |
| 598 | 805 | ||
| 599 | static int acpi_battery_add_fs(struct acpi_device *device) | 806 | static int acpi_battery_add_fs(struct acpi_device *device) |
| 600 | { | 807 | { |
| 601 | struct proc_dir_entry *entry = NULL; | 808 | struct proc_dir_entry *entry = NULL; |
| 602 | 809 | int i; | |
| 603 | 810 | ||
| 604 | if (!acpi_device_dir(device)) { | 811 | if (!acpi_device_dir(device)) { |
| 605 | acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), | 812 | acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), |
| @@ -609,38 +816,16 @@ static int acpi_battery_add_fs(struct acpi_device *device) | |||
| 609 | acpi_device_dir(device)->owner = THIS_MODULE; | 816 | acpi_device_dir(device)->owner = THIS_MODULE; |
| 610 | } | 817 | } |
| 611 | 818 | ||
| 612 | /* 'info' [R] */ | 819 | for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) { |
| 613 | entry = create_proc_entry(ACPI_BATTERY_FILE_INFO, | 820 | entry = create_proc_entry(acpi_battery_file[i].name, |
| 614 | S_IRUGO, acpi_device_dir(device)); | 821 | acpi_battery_file[i].mode, acpi_device_dir(device)); |
| 615 | if (!entry) | 822 | if (!entry) |
| 616 | return -ENODEV; | 823 | return -ENODEV; |
| 617 | else { | 824 | else { |
| 618 | entry->proc_fops = &acpi_battery_info_ops; | 825 | entry->proc_fops = &acpi_battery_file[i].ops; |
| 619 | entry->data = acpi_driver_data(device); | 826 | entry->data = acpi_driver_data(device); |
| 620 | entry->owner = THIS_MODULE; | 827 | entry->owner = THIS_MODULE; |
| 621 | } | 828 | } |
| 622 | |||
| 623 | /* 'status' [R] */ | ||
| 624 | entry = create_proc_entry(ACPI_BATTERY_FILE_STATUS, | ||
| 625 | S_IRUGO, acpi_device_dir(device)); | ||
| 626 | if (!entry) | ||
| 627 | return -ENODEV; | ||
| 628 | else { | ||
| 629 | entry->proc_fops = &acpi_battery_state_ops; | ||
| 630 | entry->data = acpi_driver_data(device); | ||
| 631 | entry->owner = THIS_MODULE; | ||
| 632 | } | ||
| 633 | |||
| 634 | /* 'alarm' [R/W] */ | ||
| 635 | entry = create_proc_entry(ACPI_BATTERY_FILE_ALARM, | ||
| 636 | S_IFREG | S_IRUGO | S_IWUSR, | ||
| 637 | acpi_device_dir(device)); | ||
| 638 | if (!entry) | ||
| 639 | return -ENODEV; | ||
| 640 | else { | ||
| 641 | entry->proc_fops = &acpi_battery_alarm_ops; | ||
| 642 | entry->data = acpi_driver_data(device); | ||
| 643 | entry->owner = THIS_MODULE; | ||
| 644 | } | 829 | } |
| 645 | 830 | ||
| 646 | return 0; | 831 | return 0; |
| @@ -648,15 +833,12 @@ static int acpi_battery_add_fs(struct acpi_device *device) | |||
| 648 | 833 | ||
| 649 | static int acpi_battery_remove_fs(struct acpi_device *device) | 834 | static int acpi_battery_remove_fs(struct acpi_device *device) |
| 650 | { | 835 | { |
| 651 | 836 | int i; | |
| 652 | if (acpi_device_dir(device)) { | 837 | if (acpi_device_dir(device)) { |
| 653 | remove_proc_entry(ACPI_BATTERY_FILE_ALARM, | 838 | for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) { |
| 839 | remove_proc_entry(acpi_battery_file[i].name, | ||
| 654 | acpi_device_dir(device)); | 840 | acpi_device_dir(device)); |
| 655 | remove_proc_entry(ACPI_BATTERY_FILE_STATUS, | 841 | } |
| 656 | acpi_device_dir(device)); | ||
| 657 | remove_proc_entry(ACPI_BATTERY_FILE_INFO, | ||
| 658 | acpi_device_dir(device)); | ||
| 659 | |||
| 660 | remove_proc_entry(acpi_device_bid(device), acpi_battery_dir); | 842 | remove_proc_entry(acpi_device_bid(device), acpi_battery_dir); |
| 661 | acpi_device_dir(device) = NULL; | 843 | acpi_device_dir(device) = NULL; |
| 662 | } | 844 | } |
| @@ -673,7 +855,6 @@ static void acpi_battery_notify(acpi_handle handle, u32 event, void *data) | |||
| 673 | struct acpi_battery *battery = data; | 855 | struct acpi_battery *battery = data; |
| 674 | struct acpi_device *device = NULL; | 856 | struct acpi_device *device = NULL; |
| 675 | 857 | ||
| 676 | |||
| 677 | if (!battery) | 858 | if (!battery) |
| 678 | return; | 859 | return; |
| 679 | 860 | ||
| @@ -684,8 +865,10 @@ static void acpi_battery_notify(acpi_handle handle, u32 event, void *data) | |||
| 684 | case ACPI_BATTERY_NOTIFY_INFO: | 865 | case ACPI_BATTERY_NOTIFY_INFO: |
| 685 | case ACPI_NOTIFY_BUS_CHECK: | 866 | case ACPI_NOTIFY_BUS_CHECK: |
| 686 | case ACPI_NOTIFY_DEVICE_CHECK: | 867 | case ACPI_NOTIFY_DEVICE_CHECK: |
| 687 | acpi_battery_check(battery); | 868 | device = battery->device; |
| 688 | acpi_bus_generate_event(device, event, battery->flags.present); | 869 | acpi_battery_notify_update(battery); |
| 870 | acpi_bus_generate_event(device, event, | ||
| 871 | acpi_battery_present(battery)); | ||
| 689 | break; | 872 | break; |
| 690 | default: | 873 | default: |
| 691 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 874 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
| @@ -702,7 +885,6 @@ static int acpi_battery_add(struct acpi_device *device) | |||
| 702 | acpi_status status = 0; | 885 | acpi_status status = 0; |
| 703 | struct acpi_battery *battery = NULL; | 886 | struct acpi_battery *battery = NULL; |
| 704 | 887 | ||
| 705 | |||
| 706 | if (!device) | 888 | if (!device) |
| 707 | return -EINVAL; | 889 | return -EINVAL; |
| 708 | 890 | ||
| @@ -710,15 +892,21 @@ static int acpi_battery_add(struct acpi_device *device) | |||
| 710 | if (!battery) | 892 | if (!battery) |
| 711 | return -ENOMEM; | 893 | return -ENOMEM; |
| 712 | 894 | ||
| 895 | mutex_init(&battery->mutex); | ||
| 896 | |||
| 897 | mutex_lock(&battery->mutex); | ||
| 898 | |||
| 713 | battery->device = device; | 899 | battery->device = device; |
| 714 | strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME); | 900 | strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME); |
| 715 | strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS); | 901 | strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS); |
| 716 | acpi_driver_data(device) = battery; | 902 | acpi_driver_data(device) = battery; |
| 717 | 903 | ||
| 718 | result = acpi_battery_check(battery); | 904 | result = acpi_battery_get_status(battery); |
| 719 | if (result) | 905 | if (result) |
| 720 | goto end; | 906 | goto end; |
| 721 | 907 | ||
| 908 | battery->flags.init_update = 1; | ||
| 909 | |||
| 722 | result = acpi_battery_add_fs(device); | 910 | result = acpi_battery_add_fs(device); |
| 723 | if (result) | 911 | if (result) |
| 724 | goto end; | 912 | goto end; |
| @@ -727,6 +915,7 @@ static int acpi_battery_add(struct acpi_device *device) | |||
| 727 | ACPI_ALL_NOTIFY, | 915 | ACPI_ALL_NOTIFY, |
| 728 | acpi_battery_notify, battery); | 916 | acpi_battery_notify, battery); |
| 729 | if (ACPI_FAILURE(status)) { | 917 | if (ACPI_FAILURE(status)) { |
| 918 | ACPI_EXCEPTION((AE_INFO, status, "Installing notify handler")); | ||
| 730 | result = -ENODEV; | 919 | result = -ENODEV; |
| 731 | goto end; | 920 | goto end; |
| 732 | } | 921 | } |
| @@ -736,11 +925,14 @@ static int acpi_battery_add(struct acpi_device *device) | |||
| 736 | device->status.battery_present ? "present" : "absent"); | 925 | device->status.battery_present ? "present" : "absent"); |
| 737 | 926 | ||
| 738 | end: | 927 | end: |
| 928 | |||
| 739 | if (result) { | 929 | if (result) { |
| 740 | acpi_battery_remove_fs(device); | 930 | acpi_battery_remove_fs(device); |
| 741 | kfree(battery); | 931 | kfree(battery); |
| 742 | } | 932 | } |
| 743 | 933 | ||
| 934 | mutex_unlock(&battery->mutex); | ||
| 935 | |||
| 744 | return result; | 936 | return result; |
| 745 | } | 937 | } |
| 746 | 938 | ||
| @@ -749,18 +941,27 @@ static int acpi_battery_remove(struct acpi_device *device, int type) | |||
| 749 | acpi_status status = 0; | 941 | acpi_status status = 0; |
| 750 | struct acpi_battery *battery = NULL; | 942 | struct acpi_battery *battery = NULL; |
| 751 | 943 | ||
| 752 | |||
| 753 | if (!device || !acpi_driver_data(device)) | 944 | if (!device || !acpi_driver_data(device)) |
| 754 | return -EINVAL; | 945 | return -EINVAL; |
| 755 | 946 | ||
| 756 | battery = acpi_driver_data(device); | 947 | battery = acpi_driver_data(device); |
| 757 | 948 | ||
| 949 | mutex_lock(&battery->mutex); | ||
| 950 | |||
| 758 | status = acpi_remove_notify_handler(device->handle, | 951 | status = acpi_remove_notify_handler(device->handle, |
| 759 | ACPI_ALL_NOTIFY, | 952 | ACPI_ALL_NOTIFY, |
| 760 | acpi_battery_notify); | 953 | acpi_battery_notify); |
| 761 | 954 | ||
| 762 | acpi_battery_remove_fs(device); | 955 | acpi_battery_remove_fs(device); |
| 763 | 956 | ||
| 957 | kfree(battery->bif_data.pointer); | ||
| 958 | |||
| 959 | kfree(battery->bst_data.pointer); | ||
| 960 | |||
| 961 | mutex_unlock(&battery->mutex); | ||
| 962 | |||
| 963 | mutex_destroy(&battery->mutex); | ||
| 964 | |||
| 764 | kfree(battery); | 965 | kfree(battery); |
| 765 | 966 | ||
| 766 | return 0; | 967 | return 0; |
| @@ -775,7 +976,10 @@ static int acpi_battery_resume(struct acpi_device *device) | |||
| 775 | return -EINVAL; | 976 | return -EINVAL; |
| 776 | 977 | ||
| 777 | battery = device->driver_data; | 978 | battery = device->driver_data; |
| 778 | return acpi_battery_check(battery); | 979 | |
| 980 | battery->flags.init_update = 1; | ||
| 981 | |||
| 982 | return 0; | ||
| 779 | } | 983 | } |
| 780 | 984 | ||
| 781 | static int __init acpi_battery_init(void) | 985 | static int __init acpi_battery_init(void) |
| @@ -800,7 +1004,6 @@ static int __init acpi_battery_init(void) | |||
| 800 | 1004 | ||
| 801 | static void __exit acpi_battery_exit(void) | 1005 | static void __exit acpi_battery_exit(void) |
| 802 | { | 1006 | { |
| 803 | |||
| 804 | acpi_bus_unregister_driver(&acpi_battery_driver); | 1007 | acpi_bus_unregister_driver(&acpi_battery_driver); |
| 805 | 1008 | ||
| 806 | acpi_unlock_battery_dir(acpi_battery_dir); | 1009 | acpi_unlock_battery_dir(acpi_battery_dir); |
diff --git a/drivers/acpi/bay.c b/drivers/acpi/bay.c index fb3f31b5e69f..56a5b3fffeb3 100644 --- a/drivers/acpi/bay.c +++ b/drivers/acpi/bay.c | |||
| @@ -288,6 +288,11 @@ static int bay_add(acpi_handle handle, int id) | |||
| 288 | new_bay->pdev = pdev; | 288 | new_bay->pdev = pdev; |
| 289 | platform_set_drvdata(pdev, new_bay); | 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 | if (acpi_bay_add_fs(new_bay)) { | 296 | if (acpi_bay_add_fs(new_bay)) { |
| 292 | platform_device_unregister(new_bay->pdev); | 297 | platform_device_unregister(new_bay->pdev); |
| 293 | goto bay_add_err; | 298 | goto bay_add_err; |
| @@ -328,18 +333,12 @@ static void bay_notify(acpi_handle handle, u32 event, void *data) | |||
| 328 | { | 333 | { |
| 329 | struct bay *bay_dev = (struct bay *)data; | 334 | struct bay *bay_dev = (struct bay *)data; |
| 330 | struct device *dev = &bay_dev->pdev->dev; | 335 | struct device *dev = &bay_dev->pdev->dev; |
| 336 | char event_string[12]; | ||
| 337 | char *envp[] = { event_string, NULL }; | ||
| 331 | 338 | ||
| 332 | bay_dprintk(handle, "Bay event"); | 339 | bay_dprintk(handle, "Bay event"); |
| 333 | 340 | sprintf(event_string, "BAY_EVENT=%d\n", event); | |
| 334 | switch(event) { | 341 | kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); |
| 335 | case ACPI_NOTIFY_BUS_CHECK: | ||
| 336 | case ACPI_NOTIFY_DEVICE_CHECK: | ||
| 337 | case ACPI_NOTIFY_EJECT_REQUEST: | ||
| 338 | kobject_uevent(&dev->kobj, KOBJ_CHANGE); | ||
| 339 | break; | ||
| 340 | default: | ||
| 341 | printk(KERN_ERR PREFIX "Bay: unknown event %d\n", event); | ||
| 342 | } | ||
| 343 | } | 342 | } |
| 344 | 343 | ||
| 345 | static acpi_status | 344 | static acpi_status |
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index e5084ececb6f..6b2658c96242 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
| @@ -292,6 +292,10 @@ int acpi_bus_generate_event(struct acpi_device *device, u8 type, int data) | |||
| 292 | if (!device) | 292 | if (!device) |
| 293 | return -EINVAL; | 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 | /* drop event on the floor if no one's listening */ | 299 | /* drop event on the floor if no one's listening */ |
| 296 | if (!event_is_open) | 300 | if (!event_is_open) |
| 297 | return 0; | 301 | return 0; |
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 4546bf873aea..6192c8be66df 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c | |||
| @@ -40,8 +40,15 @@ MODULE_AUTHOR("Kristen Carlson Accardi"); | |||
| 40 | MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_DESCRIPTION); | 40 | MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_DESCRIPTION); |
| 41 | MODULE_LICENSE("GPL"); | 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 | static struct atomic_notifier_head dock_notifier_list; | 50 | static struct atomic_notifier_head dock_notifier_list; |
| 44 | static struct platform_device dock_device; | 51 | static struct platform_device *dock_device; |
| 45 | static char dock_device_name[] = "dock"; | 52 | static char dock_device_name[] = "dock"; |
| 46 | 53 | ||
| 47 | struct dock_station { | 54 | struct dock_station { |
| @@ -63,6 +70,7 @@ struct dock_dependent_device { | |||
| 63 | }; | 70 | }; |
| 64 | 71 | ||
| 65 | #define DOCK_DOCKING 0x00000001 | 72 | #define DOCK_DOCKING 0x00000001 |
| 73 | #define DOCK_UNDOCKING 0x00000002 | ||
| 66 | #define DOCK_EVENT 3 | 74 | #define DOCK_EVENT 3 |
| 67 | #define UNDOCK_EVENT 2 | 75 | #define UNDOCK_EVENT 2 |
| 68 | 76 | ||
| @@ -327,12 +335,20 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event) | |||
| 327 | 335 | ||
| 328 | static void dock_event(struct dock_station *ds, u32 event, int num) | 336 | static void dock_event(struct dock_station *ds, u32 event, int num) |
| 329 | { | 337 | { |
| 330 | struct device *dev = &dock_device.dev; | 338 | struct device *dev = &dock_device->dev; |
| 339 | char event_string[7]; | ||
| 340 | char *envp[] = { event_string, NULL }; | ||
| 341 | |||
| 342 | if (num == UNDOCK_EVENT) | ||
| 343 | sprintf(event_string, "UNDOCK"); | ||
| 344 | else | ||
| 345 | sprintf(event_string, "DOCK"); | ||
| 346 | |||
| 331 | /* | 347 | /* |
| 332 | * Indicate that the status of the dock station has | 348 | * Indicate that the status of the dock station has |
| 333 | * changed. | 349 | * changed. |
| 334 | */ | 350 | */ |
| 335 | kobject_uevent(&dev->kobj, KOBJ_CHANGE); | 351 | kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); |
| 336 | } | 352 | } |
| 337 | 353 | ||
| 338 | /** | 354 | /** |
| @@ -380,12 +396,11 @@ static void handle_dock(struct dock_station *ds, int dock) | |||
| 380 | union acpi_object arg; | 396 | union acpi_object arg; |
| 381 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 397 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
| 382 | struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 398 | struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
| 383 | union acpi_object *obj; | ||
| 384 | 399 | ||
| 385 | acpi_get_name(ds->handle, ACPI_FULL_PATHNAME, &name_buffer); | 400 | acpi_get_name(ds->handle, ACPI_FULL_PATHNAME, &name_buffer); |
| 386 | obj = name_buffer.pointer; | ||
| 387 | 401 | ||
| 388 | printk(KERN_INFO PREFIX "%s\n", dock ? "docking" : "undocking"); | 402 | printk(KERN_INFO PREFIX "%s - %s\n", |
| 403 | (char *)name_buffer.pointer, dock ? "docking" : "undocking"); | ||
| 389 | 404 | ||
| 390 | /* _DCK method has one argument */ | 405 | /* _DCK method has one argument */ |
| 391 | arg_list.count = 1; | 406 | arg_list.count = 1; |
| @@ -394,7 +409,8 @@ static void handle_dock(struct dock_station *ds, int dock) | |||
| 394 | arg.integer.value = dock; | 409 | arg.integer.value = dock; |
| 395 | status = acpi_evaluate_object(ds->handle, "_DCK", &arg_list, &buffer); | 410 | status = acpi_evaluate_object(ds->handle, "_DCK", &arg_list, &buffer); |
| 396 | if (ACPI_FAILURE(status)) | 411 | if (ACPI_FAILURE(status)) |
| 397 | pr_debug("%s: failed to execute _DCK\n", obj->string.pointer); | 412 | printk(KERN_ERR PREFIX "%s - failed to execute _DCK\n", |
| 413 | (char *)name_buffer.pointer); | ||
| 398 | kfree(buffer.pointer); | 414 | kfree(buffer.pointer); |
| 399 | kfree(name_buffer.pointer); | 415 | kfree(name_buffer.pointer); |
| 400 | } | 416 | } |
| @@ -420,6 +436,16 @@ static inline void complete_dock(struct dock_station *ds) | |||
| 420 | ds->last_dock_time = jiffies; | 436 | ds->last_dock_time = jiffies; |
| 421 | } | 437 | } |
| 422 | 438 | ||
| 439 | static inline void begin_undock(struct dock_station *ds) | ||
| 440 | { | ||
| 441 | ds->flags |= DOCK_UNDOCKING; | ||
| 442 | } | ||
| 443 | |||
| 444 | static inline void complete_undock(struct dock_station *ds) | ||
| 445 | { | ||
| 446 | ds->flags &= ~(DOCK_UNDOCKING); | ||
| 447 | } | ||
| 448 | |||
| 423 | /** | 449 | /** |
| 424 | * dock_in_progress - see if we are in the middle of handling a dock event | 450 | * dock_in_progress - see if we are in the middle of handling a dock event |
| 425 | * @ds: the dock station | 451 | * @ds: the dock station |
| @@ -550,7 +576,7 @@ static int handle_eject_request(struct dock_station *ds, u32 event) | |||
| 550 | printk(KERN_ERR PREFIX "Unable to undock!\n"); | 576 | printk(KERN_ERR PREFIX "Unable to undock!\n"); |
| 551 | return -EBUSY; | 577 | return -EBUSY; |
| 552 | } | 578 | } |
| 553 | 579 | complete_undock(ds); | |
| 554 | return 0; | 580 | return 0; |
| 555 | } | 581 | } |
| 556 | 582 | ||
| @@ -594,7 +620,11 @@ static void dock_notify(acpi_handle handle, u32 event, void *data) | |||
| 594 | * to the driver who wish to hotplug. | 620 | * to the driver who wish to hotplug. |
| 595 | */ | 621 | */ |
| 596 | case ACPI_NOTIFY_EJECT_REQUEST: | 622 | case ACPI_NOTIFY_EJECT_REQUEST: |
| 597 | handle_eject_request(ds, event); | 623 | begin_undock(ds); |
| 624 | if (immediate_undock) | ||
| 625 | handle_eject_request(ds, event); | ||
| 626 | else | ||
| 627 | dock_event(ds, event, UNDOCK_EVENT); | ||
| 598 | break; | 628 | break; |
| 599 | default: | 629 | default: |
| 600 | printk(KERN_ERR PREFIX "Unknown dock event %d\n", event); | 630 | printk(KERN_ERR PREFIX "Unknown dock event %d\n", event); |
| @@ -653,6 +683,17 @@ static ssize_t show_docked(struct device *dev, | |||
| 653 | DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL); | 683 | DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL); |
| 654 | 684 | ||
| 655 | /* | 685 | /* |
| 686 | * show_flags - read method for flags file in sysfs | ||
| 687 | */ | ||
| 688 | static ssize_t show_flags(struct device *dev, | ||
| 689 | struct device_attribute *attr, char *buf) | ||
| 690 | { | ||
| 691 | return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags); | ||
| 692 | |||
| 693 | } | ||
| 694 | DEVICE_ATTR(flags, S_IRUGO, show_flags, NULL); | ||
| 695 | |||
| 696 | /* | ||
| 656 | * write_undock - write method for "undock" file in sysfs | 697 | * write_undock - write method for "undock" file in sysfs |
| 657 | */ | 698 | */ |
| 658 | static ssize_t write_undock(struct device *dev, struct device_attribute *attr, | 699 | static ssize_t write_undock(struct device *dev, struct device_attribute *attr, |
| @@ -675,16 +716,15 @@ static ssize_t show_dock_uid(struct device *dev, | |||
| 675 | struct device_attribute *attr, char *buf) | 716 | struct device_attribute *attr, char *buf) |
| 676 | { | 717 | { |
| 677 | unsigned long lbuf; | 718 | unsigned long lbuf; |
| 678 | acpi_status status = acpi_evaluate_integer(dock_station->handle, "_UID", NULL, &lbuf); | 719 | acpi_status status = acpi_evaluate_integer(dock_station->handle, |
| 679 | if(ACPI_FAILURE(status)) { | 720 | "_UID", NULL, &lbuf); |
| 721 | if (ACPI_FAILURE(status)) | ||
| 680 | return 0; | 722 | return 0; |
| 681 | } | 723 | |
| 682 | return snprintf(buf, PAGE_SIZE, "%lx\n", lbuf); | 724 | return snprintf(buf, PAGE_SIZE, "%lx\n", lbuf); |
| 683 | } | 725 | } |
| 684 | DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL); | 726 | DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL); |
| 685 | 727 | ||
| 686 | |||
| 687 | |||
| 688 | /** | 728 | /** |
| 689 | * dock_add - add a new dock station | 729 | * dock_add - add a new dock station |
| 690 | * @handle: the dock station handle | 730 | * @handle: the dock station handle |
| @@ -711,33 +751,53 @@ static int dock_add(acpi_handle handle) | |||
| 711 | ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list); | 751 | ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list); |
| 712 | 752 | ||
| 713 | /* initialize platform device stuff */ | 753 | /* initialize platform device stuff */ |
| 714 | dock_device.name = dock_device_name; | 754 | dock_device = |
| 715 | ret = platform_device_register(&dock_device); | 755 | platform_device_register_simple(dock_device_name, 0, NULL, 0); |
| 756 | if (IS_ERR(dock_device)) { | ||
| 757 | kfree(dock_station); | ||
| 758 | dock_station = NULL; | ||
| 759 | return PTR_ERR(dock_device); | ||
| 760 | } | ||
| 761 | |||
| 762 | /* we want the dock device to send uevents */ | ||
| 763 | dock_device->dev.uevent_suppress = 0; | ||
| 764 | |||
| 765 | ret = device_create_file(&dock_device->dev, &dev_attr_docked); | ||
| 716 | if (ret) { | 766 | if (ret) { |
| 717 | printk(KERN_ERR PREFIX "Error %d registering dock device\n", ret); | 767 | printk("Error %d adding sysfs file\n", ret); |
| 768 | platform_device_unregister(dock_device); | ||
| 718 | kfree(dock_station); | 769 | kfree(dock_station); |
| 770 | dock_station = NULL; | ||
| 719 | return ret; | 771 | return ret; |
| 720 | } | 772 | } |
| 721 | ret = device_create_file(&dock_device.dev, &dev_attr_docked); | 773 | ret = device_create_file(&dock_device->dev, &dev_attr_undock); |
| 722 | if (ret) { | 774 | if (ret) { |
| 723 | printk("Error %d adding sysfs file\n", ret); | 775 | printk("Error %d adding sysfs file\n", ret); |
| 724 | platform_device_unregister(&dock_device); | 776 | device_remove_file(&dock_device->dev, &dev_attr_docked); |
| 777 | platform_device_unregister(dock_device); | ||
| 725 | kfree(dock_station); | 778 | kfree(dock_station); |
| 779 | dock_station = NULL; | ||
| 726 | return ret; | 780 | return ret; |
| 727 | } | 781 | } |
| 728 | ret = device_create_file(&dock_device.dev, &dev_attr_undock); | 782 | ret = device_create_file(&dock_device->dev, &dev_attr_uid); |
| 729 | if (ret) { | 783 | if (ret) { |
| 730 | printk("Error %d adding sysfs file\n", ret); | 784 | printk("Error %d adding sysfs file\n", ret); |
| 731 | device_remove_file(&dock_device.dev, &dev_attr_docked); | 785 | device_remove_file(&dock_device->dev, &dev_attr_docked); |
| 732 | platform_device_unregister(&dock_device); | 786 | device_remove_file(&dock_device->dev, &dev_attr_undock); |
| 787 | platform_device_unregister(dock_device); | ||
| 733 | kfree(dock_station); | 788 | kfree(dock_station); |
| 789 | dock_station = NULL; | ||
| 734 | return ret; | 790 | return ret; |
| 735 | } | 791 | } |
| 736 | ret = device_create_file(&dock_device.dev, &dev_attr_uid); | 792 | ret = device_create_file(&dock_device->dev, &dev_attr_flags); |
| 737 | if (ret) { | 793 | if (ret) { |
| 738 | printk("Error %d adding sysfs file\n", ret); | 794 | printk("Error %d adding sysfs file\n", ret); |
| 739 | platform_device_unregister(&dock_device); | 795 | device_remove_file(&dock_device->dev, &dev_attr_docked); |
| 796 | device_remove_file(&dock_device->dev, &dev_attr_undock); | ||
| 797 | device_remove_file(&dock_device->dev, &dev_attr_uid); | ||
| 798 | platform_device_unregister(dock_device); | ||
| 740 | kfree(dock_station); | 799 | kfree(dock_station); |
| 800 | dock_station = NULL; | ||
| 741 | return ret; | 801 | return ret; |
| 742 | } | 802 | } |
| 743 | 803 | ||
| @@ -750,6 +810,7 @@ static int dock_add(acpi_handle handle) | |||
| 750 | dd = alloc_dock_dependent_device(handle); | 810 | dd = alloc_dock_dependent_device(handle); |
| 751 | if (!dd) { | 811 | if (!dd) { |
| 752 | kfree(dock_station); | 812 | kfree(dock_station); |
| 813 | dock_station = NULL; | ||
| 753 | ret = -ENOMEM; | 814 | ret = -ENOMEM; |
| 754 | goto dock_add_err_unregister; | 815 | goto dock_add_err_unregister; |
| 755 | } | 816 | } |
| @@ -773,10 +834,13 @@ static int dock_add(acpi_handle handle) | |||
| 773 | dock_add_err: | 834 | dock_add_err: |
| 774 | kfree(dd); | 835 | kfree(dd); |
| 775 | dock_add_err_unregister: | 836 | dock_add_err_unregister: |
| 776 | device_remove_file(&dock_device.dev, &dev_attr_docked); | 837 | device_remove_file(&dock_device->dev, &dev_attr_docked); |
| 777 | device_remove_file(&dock_device.dev, &dev_attr_undock); | 838 | device_remove_file(&dock_device->dev, &dev_attr_undock); |
| 778 | platform_device_unregister(&dock_device); | 839 | device_remove_file(&dock_device->dev, &dev_attr_uid); |
| 840 | device_remove_file(&dock_device->dev, &dev_attr_flags); | ||
| 841 | platform_device_unregister(dock_device); | ||
| 779 | kfree(dock_station); | 842 | kfree(dock_station); |
| 843 | dock_station = NULL; | ||
| 780 | return ret; | 844 | return ret; |
| 781 | } | 845 | } |
| 782 | 846 | ||
| @@ -804,12 +868,15 @@ static int dock_remove(void) | |||
| 804 | printk(KERN_ERR "Error removing notify handler\n"); | 868 | printk(KERN_ERR "Error removing notify handler\n"); |
| 805 | 869 | ||
| 806 | /* cleanup sysfs */ | 870 | /* cleanup sysfs */ |
| 807 | device_remove_file(&dock_device.dev, &dev_attr_docked); | 871 | device_remove_file(&dock_device->dev, &dev_attr_docked); |
| 808 | device_remove_file(&dock_device.dev, &dev_attr_undock); | 872 | device_remove_file(&dock_device->dev, &dev_attr_undock); |
| 809 | platform_device_unregister(&dock_device); | 873 | device_remove_file(&dock_device->dev, &dev_attr_uid); |
| 874 | device_remove_file(&dock_device->dev, &dev_attr_flags); | ||
| 875 | platform_device_unregister(dock_device); | ||
| 810 | 876 | ||
| 811 | /* free dock station memory */ | 877 | /* free dock station memory */ |
| 812 | kfree(dock_station); | 878 | kfree(dock_station); |
| 879 | dock_station = NULL; | ||
| 813 | return 0; | 880 | return 0; |
| 814 | } | 881 | } |
| 815 | 882 | ||
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 82f496c07675..10e851021eca 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
| @@ -34,25 +34,26 @@ | |||
| 34 | #include <linux/proc_fs.h> | 34 | #include <linux/proc_fs.h> |
| 35 | #include <linux/seq_file.h> | 35 | #include <linux/seq_file.h> |
| 36 | #include <linux/interrupt.h> | 36 | #include <linux/interrupt.h> |
| 37 | #include <linux/list.h> | ||
| 37 | #include <asm/io.h> | 38 | #include <asm/io.h> |
| 38 | #include <acpi/acpi_bus.h> | 39 | #include <acpi/acpi_bus.h> |
| 39 | #include <acpi/acpi_drivers.h> | 40 | #include <acpi/acpi_drivers.h> |
| 40 | #include <acpi/actypes.h> | 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 | #define ACPI_EC_CLASS "embedded_controller" | 43 | #define ACPI_EC_CLASS "embedded_controller" |
| 46 | #define ACPI_EC_HID "PNP0C09" | 44 | #define ACPI_EC_HID "PNP0C09" |
| 47 | #define ACPI_EC_DEVICE_NAME "Embedded Controller" | 45 | #define ACPI_EC_DEVICE_NAME "Embedded Controller" |
| 48 | #define ACPI_EC_FILE_INFO "info" | 46 | #define ACPI_EC_FILE_INFO "info" |
| 47 | |||
| 49 | #undef PREFIX | 48 | #undef PREFIX |
| 50 | #define PREFIX "ACPI: EC: " | 49 | #define PREFIX "ACPI: EC: " |
| 50 | |||
| 51 | /* EC status register */ | 51 | /* EC status register */ |
| 52 | #define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ | 52 | #define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ |
| 53 | #define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ | 53 | #define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ |
| 54 | #define ACPI_EC_FLAG_BURST 0x10 /* burst mode */ | 54 | #define ACPI_EC_FLAG_BURST 0x10 /* burst mode */ |
| 55 | #define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */ | 55 | #define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */ |
| 56 | |||
| 56 | /* EC commands */ | 57 | /* EC commands */ |
| 57 | enum ec_command { | 58 | enum ec_command { |
| 58 | ACPI_EC_COMMAND_READ = 0x80, | 59 | ACPI_EC_COMMAND_READ = 0x80, |
| @@ -61,6 +62,7 @@ enum ec_command { | |||
| 61 | ACPI_EC_BURST_DISABLE = 0x83, | 62 | ACPI_EC_BURST_DISABLE = 0x83, |
| 62 | ACPI_EC_COMMAND_QUERY = 0x84, | 63 | ACPI_EC_COMMAND_QUERY = 0x84, |
| 63 | }; | 64 | }; |
| 65 | |||
| 64 | /* EC events */ | 66 | /* EC events */ |
| 65 | enum ec_event { | 67 | enum ec_event { |
| 66 | ACPI_EC_EVENT_OBF_1 = 1, /* Output buffer full */ | 68 | ACPI_EC_EVENT_OBF_1 = 1, /* Output buffer full */ |
| @@ -94,6 +96,16 @@ static struct acpi_driver acpi_ec_driver = { | |||
| 94 | 96 | ||
| 95 | /* If we find an EC via the ECDT, we need to keep a ptr to its context */ | 97 | /* If we find an EC via the ECDT, we need to keep a ptr to its context */ |
| 96 | /* External interfaces use first EC only, so remember */ | 98 | /* External interfaces use first EC only, so remember */ |
| 99 | typedef int (*acpi_ec_query_func) (void *data); | ||
| 100 | |||
| 101 | struct acpi_ec_query_handler { | ||
| 102 | struct list_head node; | ||
| 103 | acpi_ec_query_func func; | ||
| 104 | acpi_handle handle; | ||
| 105 | void *data; | ||
| 106 | u8 query_bit; | ||
| 107 | }; | ||
| 108 | |||
| 97 | static struct acpi_ec { | 109 | static struct acpi_ec { |
| 98 | acpi_handle handle; | 110 | acpi_handle handle; |
| 99 | unsigned long gpe; | 111 | unsigned long gpe; |
| @@ -104,6 +116,7 @@ static struct acpi_ec { | |||
| 104 | atomic_t query_pending; | 116 | atomic_t query_pending; |
| 105 | atomic_t event_count; | 117 | atomic_t event_count; |
| 106 | wait_queue_head_t wait; | 118 | wait_queue_head_t wait; |
| 119 | struct list_head list; | ||
| 107 | } *boot_ec, *first_ec; | 120 | } *boot_ec, *first_ec; |
| 108 | 121 | ||
| 109 | /* -------------------------------------------------------------------------- | 122 | /* -------------------------------------------------------------------------- |
| @@ -245,7 +258,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, | |||
| 245 | 258 | ||
| 246 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0, 0); | 259 | status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0, 0); |
| 247 | if (status) { | 260 | if (status) { |
| 248 | printk(KERN_DEBUG PREFIX | 261 | printk(KERN_ERR PREFIX |
| 249 | "input buffer is not empty, aborting transaction\n"); | 262 | "input buffer is not empty, aborting transaction\n"); |
| 250 | goto end; | 263 | goto end; |
| 251 | } | 264 | } |
| @@ -394,21 +407,67 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data) | |||
| 394 | /* -------------------------------------------------------------------------- | 407 | /* -------------------------------------------------------------------------- |
| 395 | Event Management | 408 | Event Management |
| 396 | -------------------------------------------------------------------------- */ | 409 | -------------------------------------------------------------------------- */ |
| 410 | int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit, | ||
| 411 | acpi_handle handle, acpi_ec_query_func func, | ||
| 412 | void *data) | ||
| 413 | { | ||
| 414 | struct acpi_ec_query_handler *handler = | ||
| 415 | kzalloc(sizeof(struct acpi_ec_query_handler), GFP_KERNEL); | ||
| 416 | if (!handler) | ||
| 417 | return -ENOMEM; | ||
| 418 | |||
| 419 | handler->query_bit = query_bit; | ||
| 420 | handler->handle = handle; | ||
| 421 | handler->func = func; | ||
| 422 | handler->data = data; | ||
| 423 | mutex_lock(&ec->lock); | ||
| 424 | list_add_tail(&handler->node, &ec->list); | ||
| 425 | mutex_unlock(&ec->lock); | ||
| 426 | return 0; | ||
| 427 | } | ||
| 428 | |||
| 429 | EXPORT_SYMBOL_GPL(acpi_ec_add_query_handler); | ||
| 430 | |||
| 431 | void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit) | ||
| 432 | { | ||
| 433 | struct acpi_ec_query_handler *handler; | ||
| 434 | mutex_lock(&ec->lock); | ||
| 435 | list_for_each_entry(handler, &ec->list, node) { | ||
| 436 | if (query_bit == handler->query_bit) { | ||
| 437 | list_del(&handler->node); | ||
| 438 | kfree(handler); | ||
| 439 | break; | ||
| 440 | } | ||
| 441 | } | ||
| 442 | mutex_unlock(&ec->lock); | ||
| 443 | } | ||
| 444 | |||
| 445 | EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler); | ||
| 397 | 446 | ||
| 398 | static void acpi_ec_gpe_query(void *ec_cxt) | 447 | static void acpi_ec_gpe_query(void *ec_cxt) |
| 399 | { | 448 | { |
| 400 | struct acpi_ec *ec = ec_cxt; | 449 | struct acpi_ec *ec = ec_cxt; |
| 401 | u8 value = 0; | 450 | u8 value = 0; |
| 402 | char object_name[8]; | 451 | struct acpi_ec_query_handler *handler, copy; |
| 403 | 452 | ||
| 404 | if (!ec || acpi_ec_query(ec, &value)) | 453 | if (!ec || acpi_ec_query(ec, &value)) |
| 405 | return; | 454 | return; |
| 406 | 455 | mutex_lock(&ec->lock); | |
| 407 | snprintf(object_name, 8, "_Q%2.2X", value); | 456 | list_for_each_entry(handler, &ec->list, node) { |
| 408 | 457 | if (value == handler->query_bit) { | |
| 409 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s", object_name)); | 458 | /* have custom handler for this bit */ |
| 410 | 459 | memcpy(©, handler, sizeof(copy)); | |
| 411 | acpi_evaluate_object(ec->handle, object_name, NULL, NULL); | 460 | mutex_unlock(&ec->lock); |
| 461 | if (copy.func) { | ||
| 462 | copy.func(copy.data); | ||
| 463 | } else if (copy.handle) { | ||
| 464 | acpi_evaluate_object(copy.handle, NULL, NULL, NULL); | ||
| 465 | } | ||
| 466 | return; | ||
| 467 | } | ||
| 468 | } | ||
| 469 | mutex_unlock(&ec->lock); | ||
| 470 | printk(KERN_ERR PREFIX "Handler for query 0x%x is not found!\n", value); | ||
| 412 | } | 471 | } |
| 413 | 472 | ||
| 414 | static u32 acpi_ec_gpe_handler(void *data) | 473 | static u32 acpi_ec_gpe_handler(void *data) |
| @@ -427,8 +486,7 @@ static u32 acpi_ec_gpe_handler(void *data) | |||
| 427 | if ((value & ACPI_EC_FLAG_SCI) && !atomic_read(&ec->query_pending)) { | 486 | if ((value & ACPI_EC_FLAG_SCI) && !atomic_read(&ec->query_pending)) { |
| 428 | atomic_set(&ec->query_pending, 1); | 487 | atomic_set(&ec->query_pending, 1); |
| 429 | status = | 488 | status = |
| 430 | acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, | 489 | acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, ec); |
| 431 | ec); | ||
| 432 | } | 490 | } |
| 433 | 491 | ||
| 434 | return status == AE_OK ? | 492 | return status == AE_OK ? |
| @@ -454,57 +512,35 @@ acpi_ec_space_setup(acpi_handle region_handle, | |||
| 454 | } | 512 | } |
| 455 | 513 | ||
| 456 | static acpi_status | 514 | static acpi_status |
| 457 | acpi_ec_space_handler(u32 function, | 515 | acpi_ec_space_handler(u32 function, acpi_physical_address address, |
| 458 | acpi_physical_address address, | 516 | u32 bits, acpi_integer *value, |
| 459 | u32 bit_width, | ||
| 460 | acpi_integer * value, | ||
| 461 | void *handler_context, void *region_context) | 517 | void *handler_context, void *region_context) |
| 462 | { | 518 | { |
| 463 | int result = 0; | ||
| 464 | struct acpi_ec *ec = handler_context; | 519 | struct acpi_ec *ec = handler_context; |
| 465 | u64 temp = *value; | 520 | int result = 0, i = 0; |
| 466 | acpi_integer f_v = 0; | 521 | u8 temp = 0; |
| 467 | int i = 0; | ||
| 468 | 522 | ||
| 469 | if ((address > 0xFF) || !value || !handler_context) | 523 | if ((address > 0xFF) || !value || !handler_context) |
| 470 | return AE_BAD_PARAMETER; | 524 | return AE_BAD_PARAMETER; |
| 471 | 525 | ||
| 472 | if (bit_width != 8 && acpi_strict) { | 526 | if (function != ACPI_READ && function != ACPI_WRITE) |
| 473 | return AE_BAD_PARAMETER; | 527 | return AE_BAD_PARAMETER; |
| 474 | } | ||
| 475 | |||
| 476 | next_byte: | ||
| 477 | switch (function) { | ||
| 478 | case ACPI_READ: | ||
| 479 | temp = 0; | ||
| 480 | result = acpi_ec_read(ec, (u8) address, (u8 *) & temp); | ||
| 481 | break; | ||
| 482 | case ACPI_WRITE: | ||
| 483 | result = acpi_ec_write(ec, (u8) address, (u8) temp); | ||
| 484 | break; | ||
| 485 | default: | ||
| 486 | result = -EINVAL; | ||
| 487 | goto out; | ||
| 488 | break; | ||
| 489 | } | ||
| 490 | 528 | ||
| 491 | bit_width -= 8; | 529 | if (bits != 8 && acpi_strict) |
| 492 | if (bit_width) { | 530 | return AE_BAD_PARAMETER; |
| 493 | if (function == ACPI_READ) | ||
| 494 | f_v |= temp << 8 * i; | ||
| 495 | if (function == ACPI_WRITE) | ||
| 496 | temp >>= 8; | ||
| 497 | i++; | ||
| 498 | address++; | ||
| 499 | goto next_byte; | ||
| 500 | } | ||
| 501 | 531 | ||
| 502 | if (function == ACPI_READ) { | 532 | while (bits - i > 0) { |
| 503 | f_v |= temp << 8 * i; | 533 | if (function == ACPI_READ) { |
| 504 | *value = f_v; | 534 | result = acpi_ec_read(ec, address, &temp); |
| 535 | (*value) |= ((acpi_integer)temp) << i; | ||
| 536 | } else { | ||
| 537 | temp = 0xff & ((*value) >> i); | ||
| 538 | result = acpi_ec_write(ec, address, temp); | ||
| 539 | } | ||
| 540 | i += 8; | ||
| 541 | ++address; | ||
| 505 | } | 542 | } |
| 506 | 543 | ||
| 507 | out: | ||
| 508 | switch (result) { | 544 | switch (result) { |
| 509 | case -EINVAL: | 545 | case -EINVAL: |
| 510 | return AE_BAD_PARAMETER; | 546 | return AE_BAD_PARAMETER; |
| @@ -597,9 +633,6 @@ static int acpi_ec_remove_fs(struct acpi_device *device) | |||
| 597 | static acpi_status | 633 | static acpi_status |
| 598 | ec_parse_io_ports(struct acpi_resource *resource, void *context); | 634 | ec_parse_io_ports(struct acpi_resource *resource, void *context); |
| 599 | 635 | ||
| 600 | static acpi_status | ||
| 601 | ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval); | ||
| 602 | |||
| 603 | static struct acpi_ec *make_acpi_ec(void) | 636 | static struct acpi_ec *make_acpi_ec(void) |
| 604 | { | 637 | { |
| 605 | struct acpi_ec *ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL); | 638 | struct acpi_ec *ec = kzalloc(sizeof(struct acpi_ec), GFP_KERNEL); |
| @@ -610,13 +643,52 @@ static struct acpi_ec *make_acpi_ec(void) | |||
| 610 | atomic_set(&ec->event_count, 1); | 643 | atomic_set(&ec->event_count, 1); |
| 611 | mutex_init(&ec->lock); | 644 | mutex_init(&ec->lock); |
| 612 | init_waitqueue_head(&ec->wait); | 645 | init_waitqueue_head(&ec->wait); |
| 646 | INIT_LIST_HEAD(&ec->list); | ||
| 613 | 647 | ||
| 614 | return ec; | 648 | return ec; |
| 615 | } | 649 | } |
| 616 | 650 | ||
| 651 | static acpi_status | ||
| 652 | acpi_ec_register_query_methods(acpi_handle handle, u32 level, | ||
| 653 | void *context, void **return_value) | ||
| 654 | { | ||
| 655 | struct acpi_namespace_node *node = handle; | ||
| 656 | struct acpi_ec *ec = context; | ||
| 657 | int value = 0; | ||
| 658 | if (sscanf(node->name.ascii, "_Q%x", &value) == 1) { | ||
| 659 | acpi_ec_add_query_handler(ec, value, handle, NULL, NULL); | ||
| 660 | } | ||
| 661 | return AE_OK; | ||
| 662 | } | ||
| 663 | |||
| 664 | static int ec_parse_device(struct acpi_ec *ec, acpi_handle handle) | ||
| 665 | { | ||
| 666 | if (ACPI_FAILURE(acpi_walk_resources(handle, METHOD_NAME__CRS, | ||
| 667 | ec_parse_io_ports, ec))) | ||
| 668 | return -EINVAL; | ||
| 669 | |||
| 670 | /* Get GPE bit assignment (EC events). */ | ||
| 671 | /* TODO: Add support for _GPE returning a package */ | ||
| 672 | if (ACPI_FAILURE(acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe))) | ||
| 673 | return -EINVAL; | ||
| 674 | |||
| 675 | /* Use the global lock for all EC transactions? */ | ||
| 676 | acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock); | ||
| 677 | |||
| 678 | /* Find and register all query methods */ | ||
| 679 | acpi_walk_namespace(ACPI_TYPE_METHOD, handle, 1, | ||
| 680 | acpi_ec_register_query_methods, ec, NULL); | ||
| 681 | |||
| 682 | ec->handle = handle; | ||
| 683 | |||
| 684 | printk(KERN_INFO PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx", | ||
| 685 | ec->gpe, ec->command_addr, ec->data_addr); | ||
| 686 | |||
| 687 | return 0; | ||
| 688 | } | ||
| 689 | |||
| 617 | static int acpi_ec_add(struct acpi_device *device) | 690 | static int acpi_ec_add(struct acpi_device *device) |
| 618 | { | 691 | { |
| 619 | acpi_status status = AE_OK; | ||
| 620 | struct acpi_ec *ec = NULL; | 692 | struct acpi_ec *ec = NULL; |
| 621 | 693 | ||
| 622 | if (!device) | 694 | if (!device) |
| @@ -629,8 +701,7 @@ static int acpi_ec_add(struct acpi_device *device) | |||
| 629 | if (!ec) | 701 | if (!ec) |
| 630 | return -ENOMEM; | 702 | return -ENOMEM; |
| 631 | 703 | ||
| 632 | status = ec_parse_device(device->handle, 0, ec, NULL); | 704 | if (ec_parse_device(ec, device->handle)) { |
| 633 | if (status != AE_CTRL_TERMINATE) { | ||
| 634 | kfree(ec); | 705 | kfree(ec); |
| 635 | return -EINVAL; | 706 | return -EINVAL; |
| 636 | } | 707 | } |
| @@ -641,6 +712,8 @@ static int acpi_ec_add(struct acpi_device *device) | |||
| 641 | /* We might have incorrect info for GL at boot time */ | 712 | /* We might have incorrect info for GL at boot time */ |
| 642 | mutex_lock(&boot_ec->lock); | 713 | mutex_lock(&boot_ec->lock); |
| 643 | boot_ec->global_lock = ec->global_lock; | 714 | boot_ec->global_lock = ec->global_lock; |
| 715 | /* Copy handlers from new ec into boot ec */ | ||
| 716 | list_splice(&ec->list, &boot_ec->list); | ||
| 644 | mutex_unlock(&boot_ec->lock); | 717 | mutex_unlock(&boot_ec->lock); |
| 645 | kfree(ec); | 718 | kfree(ec); |
| 646 | ec = boot_ec; | 719 | ec = boot_ec; |
| @@ -651,22 +724,24 @@ static int acpi_ec_add(struct acpi_device *device) | |||
| 651 | acpi_driver_data(device) = ec; | 724 | acpi_driver_data(device) = ec; |
| 652 | 725 | ||
| 653 | acpi_ec_add_fs(device); | 726 | acpi_ec_add_fs(device); |
| 654 | |||
| 655 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s [%s] (gpe %d) interrupt mode.", | ||
| 656 | acpi_device_name(device), acpi_device_bid(device), | ||
| 657 | (u32) ec->gpe)); | ||
| 658 | |||
| 659 | return 0; | 727 | return 0; |
| 660 | } | 728 | } |
| 661 | 729 | ||
| 662 | static int acpi_ec_remove(struct acpi_device *device, int type) | 730 | static int acpi_ec_remove(struct acpi_device *device, int type) |
| 663 | { | 731 | { |
| 664 | struct acpi_ec *ec; | 732 | struct acpi_ec *ec; |
| 733 | struct acpi_ec_query_handler *handler; | ||
| 665 | 734 | ||
| 666 | if (!device) | 735 | if (!device) |
| 667 | return -EINVAL; | 736 | return -EINVAL; |
| 668 | 737 | ||
| 669 | ec = acpi_driver_data(device); | 738 | ec = acpi_driver_data(device); |
| 739 | mutex_lock(&ec->lock); | ||
| 740 | list_for_each_entry(handler, &ec->list, node) { | ||
| 741 | list_del(&handler->node); | ||
| 742 | kfree(handler); | ||
| 743 | } | ||
| 744 | mutex_unlock(&ec->lock); | ||
| 670 | acpi_ec_remove_fs(device); | 745 | acpi_ec_remove_fs(device); |
| 671 | acpi_driver_data(device) = NULL; | 746 | acpi_driver_data(device) = NULL; |
| 672 | if (ec == first_ec) | 747 | if (ec == first_ec) |
| @@ -722,15 +797,13 @@ static int ec_install_handlers(struct acpi_ec *ec) | |||
| 722 | return -ENODEV; | 797 | return -ENODEV; |
| 723 | } | 798 | } |
| 724 | 799 | ||
| 725 | /* EC is fully operational, allow queries */ | ||
| 726 | atomic_set(&ec->query_pending, 0); | ||
| 727 | |||
| 728 | return 0; | 800 | return 0; |
| 729 | } | 801 | } |
| 730 | 802 | ||
| 731 | static int acpi_ec_start(struct acpi_device *device) | 803 | static int acpi_ec_start(struct acpi_device *device) |
| 732 | { | 804 | { |
| 733 | struct acpi_ec *ec; | 805 | struct acpi_ec *ec; |
| 806 | int ret = 0; | ||
| 734 | 807 | ||
| 735 | if (!device) | 808 | if (!device) |
| 736 | return -EINVAL; | 809 | return -EINVAL; |
| @@ -740,14 +813,14 @@ static int acpi_ec_start(struct acpi_device *device) | |||
| 740 | if (!ec) | 813 | if (!ec) |
| 741 | return -EINVAL; | 814 | return -EINVAL; |
| 742 | 815 | ||
| 743 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02lx, ports=0x%2lx,0x%2lx", | ||
| 744 | ec->gpe, ec->command_addr, ec->data_addr)); | ||
| 745 | |||
| 746 | /* Boot EC is already working */ | 816 | /* Boot EC is already working */ |
| 747 | if (ec == boot_ec) | 817 | if (ec != boot_ec) |
| 748 | return 0; | 818 | ret = ec_install_handlers(ec); |
| 819 | |||
| 820 | /* EC is fully operational, allow queries */ | ||
| 821 | atomic_set(&ec->query_pending, 0); | ||
| 749 | 822 | ||
| 750 | return ec_install_handlers(ec); | 823 | return ret; |
| 751 | } | 824 | } |
| 752 | 825 | ||
| 753 | static int acpi_ec_stop(struct acpi_device *device, int type) | 826 | static int acpi_ec_stop(struct acpi_device *device, int type) |
| @@ -779,34 +852,6 @@ static int acpi_ec_stop(struct acpi_device *device, int type) | |||
| 779 | return 0; | 852 | return 0; |
| 780 | } | 853 | } |
| 781 | 854 | ||
| 782 | static acpi_status | ||
| 783 | ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval) | ||
| 784 | { | ||
| 785 | acpi_status status; | ||
| 786 | |||
| 787 | struct acpi_ec *ec = context; | ||
| 788 | status = acpi_walk_resources(handle, METHOD_NAME__CRS, | ||
| 789 | ec_parse_io_ports, ec); | ||
| 790 | if (ACPI_FAILURE(status)) | ||
| 791 | return status; | ||
| 792 | |||
| 793 | /* Get GPE bit assignment (EC events). */ | ||
| 794 | /* TODO: Add support for _GPE returning a package */ | ||
| 795 | status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe); | ||
| 796 | if (ACPI_FAILURE(status)) | ||
| 797 | return status; | ||
| 798 | |||
| 799 | /* Use the global lock for all EC transactions? */ | ||
| 800 | acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock); | ||
| 801 | |||
| 802 | ec->handle = handle; | ||
| 803 | |||
| 804 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "GPE=0x%02lx, ports=0x%2lx, 0x%2lx", | ||
| 805 | ec->gpe, ec->command_addr, ec->data_addr)); | ||
| 806 | |||
| 807 | return AE_CTRL_TERMINATE; | ||
| 808 | } | ||
| 809 | |||
| 810 | int __init acpi_ec_ecdt_probe(void) | 855 | int __init acpi_ec_ecdt_probe(void) |
| 811 | { | 856 | { |
| 812 | int ret; | 857 | int ret; |
| @@ -825,7 +870,7 @@ int __init acpi_ec_ecdt_probe(void) | |||
| 825 | if (ACPI_FAILURE(status)) | 870 | if (ACPI_FAILURE(status)) |
| 826 | goto error; | 871 | goto error; |
| 827 | 872 | ||
| 828 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found ECDT")); | 873 | printk(KERN_INFO PREFIX "EC description table is found, configuring boot EC\n"); |
| 829 | 874 | ||
| 830 | boot_ec->command_addr = ecdt_ptr->control.address; | 875 | boot_ec->command_addr = ecdt_ptr->control.address; |
| 831 | boot_ec->data_addr = ecdt_ptr->data.address; | 876 | boot_ec->data_addr = ecdt_ptr->data.address; |
diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c index 3b23562e6f92..dfa5853b17f0 100644 --- a/drivers/acpi/event.c +++ b/drivers/acpi/event.c | |||
| @@ -11,6 +11,8 @@ | |||
| 11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
| 12 | #include <linux/poll.h> | 12 | #include <linux/poll.h> |
| 13 | #include <acpi/acpi_drivers.h> | 13 | #include <acpi/acpi_drivers.h> |
| 14 | #include <net/netlink.h> | ||
| 15 | #include <net/genetlink.h> | ||
| 14 | 16 | ||
| 15 | #define _COMPONENT ACPI_SYSTEM_COMPONENT | 17 | #define _COMPONENT ACPI_SYSTEM_COMPONENT |
| 16 | ACPI_MODULE_NAME("event"); | 18 | ACPI_MODULE_NAME("event"); |
| @@ -48,7 +50,6 @@ acpi_system_read_event(struct file *file, char __user * buffer, size_t count, | |||
| 48 | static int chars_remaining = 0; | 50 | static int chars_remaining = 0; |
| 49 | static char *ptr; | 51 | static char *ptr; |
| 50 | 52 | ||
| 51 | |||
| 52 | if (!chars_remaining) { | 53 | if (!chars_remaining) { |
| 53 | memset(&event, 0, sizeof(struct acpi_bus_event)); | 54 | memset(&event, 0, sizeof(struct acpi_bus_event)); |
| 54 | 55 | ||
| @@ -106,23 +107,161 @@ static const struct file_operations acpi_system_event_ops = { | |||
| 106 | .poll = acpi_system_poll_event, | 107 | .poll = acpi_system_poll_event, |
| 107 | }; | 108 | }; |
| 108 | 109 | ||
| 110 | #ifdef CONFIG_NET | ||
| 111 | unsigned int acpi_event_seqnum; | ||
| 112 | struct acpi_genl_event { | ||
| 113 | acpi_device_class device_class; | ||
| 114 | char bus_id[15]; | ||
| 115 | u32 type; | ||
| 116 | u32 data; | ||
| 117 | }; | ||
| 118 | |||
| 119 | /* attributes of acpi_genl_family */ | ||
| 120 | enum { | ||
| 121 | ACPI_GENL_ATTR_UNSPEC, | ||
| 122 | ACPI_GENL_ATTR_EVENT, /* ACPI event info needed by user space */ | ||
| 123 | __ACPI_GENL_ATTR_MAX, | ||
| 124 | }; | ||
| 125 | #define ACPI_GENL_ATTR_MAX (__ACPI_GENL_ATTR_MAX - 1) | ||
| 126 | |||
| 127 | /* commands supported by the acpi_genl_family */ | ||
| 128 | enum { | ||
| 129 | ACPI_GENL_CMD_UNSPEC, | ||
| 130 | ACPI_GENL_CMD_EVENT, /* kernel->user notifications for ACPI events */ | ||
| 131 | __ACPI_GENL_CMD_MAX, | ||
| 132 | }; | ||
| 133 | #define ACPI_GENL_CMD_MAX (__ACPI_GENL_CMD_MAX - 1) | ||
| 134 | |||
| 135 | #define ACPI_GENL_FAMILY_NAME "acpi_event" | ||
| 136 | #define ACPI_GENL_VERSION 0x01 | ||
| 137 | #define ACPI_GENL_MCAST_GROUP_NAME "acpi_mc_group" | ||
| 138 | |||
| 139 | static struct genl_family acpi_event_genl_family = { | ||
| 140 | .id = GENL_ID_GENERATE, | ||
| 141 | .name = ACPI_GENL_FAMILY_NAME, | ||
| 142 | .version = ACPI_GENL_VERSION, | ||
| 143 | .maxattr = ACPI_GENL_ATTR_MAX, | ||
| 144 | }; | ||
| 145 | |||
| 146 | static struct genl_multicast_group acpi_event_mcgrp = { | ||
| 147 | .name = ACPI_GENL_MCAST_GROUP_NAME, | ||
| 148 | }; | ||
| 149 | |||
| 150 | int acpi_bus_generate_genetlink_event(struct acpi_device *device, | ||
| 151 | u8 type, int data) | ||
| 152 | { | ||
| 153 | struct sk_buff *skb; | ||
| 154 | struct nlattr *attr; | ||
| 155 | struct acpi_genl_event *event; | ||
| 156 | void *msg_header; | ||
| 157 | int size; | ||
| 158 | int result; | ||
| 159 | |||
| 160 | /* allocate memory */ | ||
| 161 | size = nla_total_size(sizeof(struct acpi_genl_event)) + | ||
| 162 | nla_total_size(0); | ||
| 163 | |||
| 164 | skb = genlmsg_new(size, GFP_ATOMIC); | ||
| 165 | if (!skb) | ||
| 166 | return -ENOMEM; | ||
| 167 | |||
| 168 | /* add the genetlink message header */ | ||
| 169 | msg_header = genlmsg_put(skb, 0, acpi_event_seqnum++, | ||
| 170 | &acpi_event_genl_family, 0, | ||
| 171 | ACPI_GENL_CMD_EVENT); | ||
| 172 | if (!msg_header) { | ||
| 173 | nlmsg_free(skb); | ||
| 174 | return -ENOMEM; | ||
| 175 | } | ||
| 176 | |||
| 177 | /* fill the data */ | ||
| 178 | attr = | ||
| 179 | nla_reserve(skb, ACPI_GENL_ATTR_EVENT, | ||
| 180 | sizeof(struct acpi_genl_event)); | ||
| 181 | if (!attr) { | ||
| 182 | nlmsg_free(skb); | ||
| 183 | return -EINVAL; | ||
| 184 | } | ||
| 185 | |||
| 186 | event = nla_data(attr); | ||
| 187 | if (!event) { | ||
| 188 | nlmsg_free(skb); | ||
| 189 | return -EINVAL; | ||
| 190 | } | ||
| 191 | |||
| 192 | memset(event, 0, sizeof(struct acpi_genl_event)); | ||
| 193 | |||
| 194 | strcpy(event->device_class, device->pnp.device_class); | ||
| 195 | strcpy(event->bus_id, device->dev.bus_id); | ||
| 196 | event->type = type; | ||
| 197 | event->data = data; | ||
| 198 | |||
| 199 | /* send multicast genetlink message */ | ||
| 200 | result = genlmsg_end(skb, msg_header); | ||
| 201 | if (result < 0) { | ||
| 202 | nlmsg_free(skb); | ||
| 203 | return result; | ||
| 204 | } | ||
| 205 | |||
| 206 | result = | ||
| 207 | genlmsg_multicast(skb, 0, acpi_event_mcgrp.id, GFP_ATOMIC); | ||
| 208 | if (result) | ||
| 209 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 210 | "Failed to send a Genetlink message!\n")); | ||
| 211 | return 0; | ||
| 212 | } | ||
| 213 | |||
| 214 | static int acpi_event_genetlink_init(void) | ||
| 215 | { | ||
| 216 | int result; | ||
| 217 | |||
| 218 | result = genl_register_family(&acpi_event_genl_family); | ||
| 219 | if (result) | ||
| 220 | return result; | ||
| 221 | |||
| 222 | result = genl_register_mc_group(&acpi_event_genl_family, | ||
| 223 | &acpi_event_mcgrp); | ||
| 224 | if (result) | ||
| 225 | genl_unregister_family(&acpi_event_genl_family); | ||
| 226 | |||
| 227 | return result; | ||
| 228 | } | ||
| 229 | |||
| 230 | #else | ||
| 231 | int acpi_bus_generate_genetlink_event(struct acpi_device *device, u8 type, | ||
| 232 | int data) | ||
| 233 | { | ||
| 234 | return 0; | ||
| 235 | } | ||
| 236 | |||
| 237 | static int acpi_event_genetlink_init(void) | ||
| 238 | { | ||
| 239 | return -ENODEV; | ||
| 240 | } | ||
| 241 | #endif | ||
| 242 | |||
| 109 | static int __init acpi_event_init(void) | 243 | static int __init acpi_event_init(void) |
| 110 | { | 244 | { |
| 111 | struct proc_dir_entry *entry; | 245 | struct proc_dir_entry *entry; |
| 112 | int error = 0; | 246 | int error = 0; |
| 113 | 247 | ||
| 114 | |||
| 115 | if (acpi_disabled) | 248 | if (acpi_disabled) |
| 116 | return 0; | 249 | return 0; |
| 117 | 250 | ||
| 251 | /* create genetlink for acpi event */ | ||
| 252 | error = acpi_event_genetlink_init(); | ||
| 253 | if (error) | ||
| 254 | printk(KERN_WARNING PREFIX | ||
| 255 | "Failed to create genetlink family for ACPI event\n"); | ||
| 256 | |||
| 118 | /* 'event' [R] */ | 257 | /* 'event' [R] */ |
| 119 | entry = create_proc_entry("event", S_IRUSR, acpi_root_dir); | 258 | entry = create_proc_entry("event", S_IRUSR, acpi_root_dir); |
| 120 | if (entry) | 259 | if (entry) |
| 121 | entry->proc_fops = &acpi_system_event_ops; | 260 | entry->proc_fops = &acpi_system_event_ops; |
| 122 | else { | 261 | else |
| 123 | error = -ENODEV; | 262 | return -ENODEV; |
| 124 | } | 263 | |
| 125 | return error; | 264 | return 0; |
| 126 | } | 265 | } |
| 127 | 266 | ||
| 128 | subsys_initcall(acpi_event_init); | 267 | fs_initcall(acpi_event_init); |
diff --git a/drivers/acpi/events/evgpeblk.c b/drivers/acpi/events/evgpeblk.c index 902c287b3a4f..361ebe6c4a6f 100644 --- a/drivers/acpi/events/evgpeblk.c +++ b/drivers/acpi/events/evgpeblk.c | |||
| @@ -586,6 +586,10 @@ acpi_ev_delete_gpe_xrupt(struct acpi_gpe_xrupt_info *gpe_xrupt) | |||
| 586 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | 586 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); |
| 587 | if (gpe_xrupt->previous) { | 587 | if (gpe_xrupt->previous) { |
| 588 | gpe_xrupt->previous->next = gpe_xrupt->next; | 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 | if (gpe_xrupt->next) { | 595 | if (gpe_xrupt->next) { |
diff --git a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c index 400d90fca966..23ee7bc4a705 100644 --- a/drivers/acpi/events/evrgnini.c +++ b/drivers/acpi/events/evrgnini.c | |||
| @@ -284,6 +284,7 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, | |||
| 284 | } | 284 | } |
| 285 | 285 | ||
| 286 | if (!pci_device_node) { | 286 | if (!pci_device_node) { |
| 287 | ACPI_FREE(pci_id); | ||
| 287 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); | 288 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); |
| 288 | } | 289 | } |
| 289 | 290 | ||
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 41427a41f620..4893e256e399 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
| @@ -16,7 +16,7 @@ | |||
| 16 | #if ACPI_GLUE_DEBUG | 16 | #if ACPI_GLUE_DEBUG |
| 17 | #define DBG(x...) printk(PREFIX x) | 17 | #define DBG(x...) printk(PREFIX x) |
| 18 | #else | 18 | #else |
| 19 | #define DBG(x...) | 19 | #define DBG(x...) do { } while(0) |
| 20 | #endif | 20 | #endif |
| 21 | static LIST_HEAD(bus_type_list); | 21 | static LIST_HEAD(bus_type_list); |
| 22 | static DECLARE_RWSEM(bus_type_sem); | 22 | static DECLARE_RWSEM(bus_type_sem); |
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 00d53c2fd1e8..12c09fafce9a 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
| @@ -77,13 +77,7 @@ static struct workqueue_struct *kacpi_notify_wq; | |||
| 77 | #define OSI_STRING_LENGTH_MAX 64 /* arbitrary */ | 77 | #define OSI_STRING_LENGTH_MAX 64 /* arbitrary */ |
| 78 | static char osi_additional_string[OSI_STRING_LENGTH_MAX]; | 78 | static char osi_additional_string[OSI_STRING_LENGTH_MAX]; |
| 79 | 79 | ||
| 80 | #define OSI_LINUX_ENABLED | 80 | static int osi_linux; /* disable _OSI(Linux) by default */ |
| 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 | |||
| 87 | 81 | ||
| 88 | #ifdef CONFIG_DMI | 82 | #ifdef CONFIG_DMI |
| 89 | static struct __initdata dmi_system_id acpi_osl_dmi_table[]; | 83 | static struct __initdata dmi_system_id acpi_osl_dmi_table[]; |
| @@ -1183,17 +1177,10 @@ acpi_os_validate_interface (char *interface) | |||
| 1183 | if (!strcmp("Linux", interface)) { | 1177 | if (!strcmp("Linux", interface)) { |
| 1184 | printk(KERN_WARNING PREFIX | 1178 | printk(KERN_WARNING PREFIX |
| 1185 | "System BIOS is requesting _OSI(Linux)\n"); | 1179 | "System BIOS is requesting _OSI(Linux)\n"); |
| 1186 | #ifdef OSI_LINUX_ENABLED | ||
| 1187 | printk(KERN_WARNING PREFIX | ||
| 1188 | "Please test with \"acpi_osi=!Linux\"\n" | ||
| 1189 | "Please send dmidecode " | ||
| 1190 | "to linux-acpi@vger.kernel.org\n"); | ||
| 1191 | #else | ||
| 1192 | printk(KERN_WARNING PREFIX | 1180 | printk(KERN_WARNING PREFIX |
| 1193 | "If \"acpi_osi=Linux\" works better,\n" | 1181 | "If \"acpi_osi=Linux\" works better,\n" |
| 1194 | "Please send dmidecode " | 1182 | "Please send dmidecode " |
| 1195 | "to linux-acpi@vger.kernel.org\n"); | 1183 | "to linux-acpi@vger.kernel.org\n"); |
| 1196 | #endif | ||
| 1197 | if(osi_linux) | 1184 | if(osi_linux) |
| 1198 | return AE_OK; | 1185 | return AE_OK; |
| 1199 | } | 1186 | } |
| @@ -1227,36 +1214,14 @@ acpi_os_validate_address ( | |||
| 1227 | } | 1214 | } |
| 1228 | 1215 | ||
| 1229 | #ifdef CONFIG_DMI | 1216 | #ifdef CONFIG_DMI |
| 1230 | #ifdef OSI_LINUX_ENABLED | ||
| 1231 | static int dmi_osi_not_linux(struct dmi_system_id *d) | ||
| 1232 | { | ||
| 1233 | printk(KERN_NOTICE "%s detected: requires not _OSI(Linux)\n", d->ident); | ||
| 1234 | enable_osi_linux(0); | ||
| 1235 | return 0; | ||
| 1236 | } | ||
| 1237 | #else | ||
| 1238 | static int dmi_osi_linux(struct dmi_system_id *d) | 1217 | static int dmi_osi_linux(struct dmi_system_id *d) |
| 1239 | { | 1218 | { |
| 1240 | printk(KERN_NOTICE "%s detected: requires _OSI(Linux)\n", d->ident); | 1219 | printk(KERN_NOTICE "%s detected: enabling _OSI(Linux)\n", d->ident); |
| 1241 | enable_osi_linux(1); | 1220 | enable_osi_linux(1); |
| 1242 | return 0; | 1221 | return 0; |
| 1243 | } | 1222 | } |
| 1244 | #endif | ||
| 1245 | 1223 | ||
| 1246 | static struct dmi_system_id acpi_osl_dmi_table[] __initdata = { | 1224 | static struct dmi_system_id acpi_osl_dmi_table[] __initdata = { |
| 1247 | #ifdef OSI_LINUX_ENABLED | ||
| 1248 | /* | ||
| 1249 | * Boxes that need NOT _OSI(Linux) | ||
| 1250 | */ | ||
| 1251 | { | ||
| 1252 | .callback = dmi_osi_not_linux, | ||
| 1253 | .ident = "Toshiba Satellite P100", | ||
| 1254 | .matches = { | ||
| 1255 | DMI_MATCH(DMI_BOARD_VENDOR, "TOSHIBA"), | ||
| 1256 | DMI_MATCH(DMI_BOARD_NAME, "Satellite P100"), | ||
| 1257 | }, | ||
| 1258 | }, | ||
| 1259 | #else | ||
| 1260 | /* | 1225 | /* |
| 1261 | * Boxes that need _OSI(Linux) | 1226 | * Boxes that need _OSI(Linux) |
| 1262 | */ | 1227 | */ |
| @@ -1268,7 +1233,6 @@ static struct dmi_system_id acpi_osl_dmi_table[] __initdata = { | |||
| 1268 | DMI_MATCH(DMI_BOARD_NAME, "MPAD-MSAE Customer Reference Boards"), | 1233 | DMI_MATCH(DMI_BOARD_NAME, "MPAD-MSAE Customer Reference Boards"), |
| 1269 | }, | 1234 | }, |
| 1270 | }, | 1235 | }, |
| 1271 | #endif | ||
| 1272 | {} | 1236 | {} |
| 1273 | }; | 1237 | }; |
| 1274 | #endif /* CONFIG_DMI */ | 1238 | #endif /* CONFIG_DMI */ |
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index acc594771379..3448edd61dc4 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c | |||
| @@ -733,7 +733,7 @@ static int acpi_pci_link_add(struct acpi_device *device) | |||
| 733 | /* query and set link->irq.active */ | 733 | /* query and set link->irq.active */ |
| 734 | acpi_pci_link_get_current(link); | 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 | acpi_device_bid(device)); | 737 | acpi_device_bid(device)); |
| 738 | for (i = 0; i < link->irq.possible_count; i++) { | 738 | for (i = 0; i < link->irq.possible_count; i++) { |
| 739 | if (link->irq.active == link->irq.possible[i]) { | 739 | if (link->irq.active == link->irq.possible[i]) { |
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index e1ca86dfdd66..81aceb5da7c7 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c | |||
| @@ -66,6 +66,7 @@ | |||
| 66 | #define ACPI_PROCESSOR_FILE_LIMIT "limit" | 66 | #define ACPI_PROCESSOR_FILE_LIMIT "limit" |
| 67 | #define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80 | 67 | #define ACPI_PROCESSOR_NOTIFY_PERFORMANCE 0x80 |
| 68 | #define ACPI_PROCESSOR_NOTIFY_POWER 0x81 | 68 | #define ACPI_PROCESSOR_NOTIFY_POWER 0x81 |
| 69 | #define ACPI_PROCESSOR_NOTIFY_THROTTLING 0x82 | ||
| 69 | 70 | ||
| 70 | #define ACPI_PROCESSOR_LIMIT_USER 0 | 71 | #define ACPI_PROCESSOR_LIMIT_USER 0 |
| 71 | #define ACPI_PROCESSOR_LIMIT_THERMAL 1 | 72 | #define ACPI_PROCESSOR_LIMIT_THERMAL 1 |
| @@ -84,6 +85,8 @@ static int acpi_processor_info_open_fs(struct inode *inode, struct file *file); | |||
| 84 | static void acpi_processor_notify(acpi_handle handle, u32 event, void *data); | 85 | static void acpi_processor_notify(acpi_handle handle, u32 event, void *data); |
| 85 | static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu); | 86 | static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu); |
| 86 | static int acpi_processor_handle_eject(struct acpi_processor *pr); | 87 | static int acpi_processor_handle_eject(struct acpi_processor *pr); |
| 88 | extern int acpi_processor_tstate_has_changed(struct acpi_processor *pr); | ||
| 89 | |||
| 87 | 90 | ||
| 88 | static struct acpi_driver acpi_processor_driver = { | 91 | static struct acpi_driver acpi_processor_driver = { |
| 89 | .name = "processor", | 92 | .name = "processor", |
| @@ -696,6 +699,9 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data) | |||
| 696 | acpi_processor_cst_has_changed(pr); | 699 | acpi_processor_cst_has_changed(pr); |
| 697 | acpi_bus_generate_event(device, event, 0); | 700 | acpi_bus_generate_event(device, event, 0); |
| 698 | break; | 701 | break; |
| 702 | case ACPI_PROCESSOR_NOTIFY_THROTTLING: | ||
| 703 | acpi_processor_tstate_has_changed(pr); | ||
| 704 | acpi_bus_generate_event(device, event, 0); | ||
| 699 | default: | 705 | default: |
| 700 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 706 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
| 701 | "Unsupported event [0x%x]\n", event)); | 707 | "Unsupported event [0x%x]\n", event)); |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index bb5d23be4260..a898991f77cb 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
| @@ -490,7 +490,17 @@ static void acpi_processor_idle(void) | |||
| 490 | 490 | ||
| 491 | case ACPI_STATE_C3: | 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 | if (atomic_inc_return(&c3_cpu_count) == | 504 | if (atomic_inc_return(&c3_cpu_count) == |
| 495 | num_online_cpus()) { | 505 | num_online_cpus()) { |
| 496 | /* | 506 | /* |
| @@ -499,7 +509,7 @@ static void acpi_processor_idle(void) | |||
| 499 | */ | 509 | */ |
| 500 | acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1); | 510 | acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1); |
| 501 | } | 511 | } |
| 502 | } else { | 512 | } else if (!pr->flags.bm_check) { |
| 503 | /* SMP with no shared cache... Invalidate cache */ | 513 | /* SMP with no shared cache... Invalidate cache */ |
| 504 | ACPI_FLUSH_CPU_CACHE(); | 514 | ACPI_FLUSH_CPU_CACHE(); |
| 505 | } | 515 | } |
| @@ -511,7 +521,7 @@ static void acpi_processor_idle(void) | |||
| 511 | acpi_cstate_enter(cx); | 521 | acpi_cstate_enter(cx); |
| 512 | /* Get end time (ticks) */ | 522 | /* Get end time (ticks) */ |
| 513 | t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); | 523 | t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); |
| 514 | if (pr->flags.bm_check) { | 524 | if (pr->flags.bm_check && pr->flags.bm_control) { |
| 515 | /* Enable bus master arbitration */ | 525 | /* Enable bus master arbitration */ |
| 516 | atomic_dec(&c3_cpu_count); | 526 | atomic_dec(&c3_cpu_count); |
| 517 | acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0); | 527 | acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0); |
| @@ -961,9 +971,9 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr, | |||
| 961 | if (pr->flags.bm_check) { | 971 | if (pr->flags.bm_check) { |
| 962 | /* bus mastering control is necessary */ | 972 | /* bus mastering control is necessary */ |
| 963 | if (!pr->flags.bm_control) { | 973 | if (!pr->flags.bm_control) { |
| 974 | /* In this case we enter C3 without bus mastering */ | ||
| 964 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 975 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
| 965 | "C3 support requires bus mastering control\n")); | 976 | "C3 support without bus mastering control\n")); |
| 966 | return; | ||
| 967 | } | 977 | } |
| 968 | } else { | 978 | } else { |
| 969 | /* | 979 | /* |
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index b33486009f41..3f55d1f90c11 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c | |||
| @@ -44,17 +44,231 @@ | |||
| 44 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT | 44 | #define _COMPONENT ACPI_PROCESSOR_COMPONENT |
| 45 | ACPI_MODULE_NAME("processor_throttling"); | 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 | Throttling Control | 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 | int state = 0; | 267 | int state = 0; |
| 53 | u32 value = 0; | 268 | u32 value = 0; |
| 54 | u32 duty_mask = 0; | 269 | u32 duty_mask = 0; |
| 55 | u32 duty_value = 0; | 270 | u32 duty_value = 0; |
| 56 | 271 | ||
| 57 | |||
| 58 | if (!pr) | 272 | if (!pr) |
| 59 | return -EINVAL; | 273 | return -EINVAL; |
| 60 | 274 | ||
| @@ -94,13 +308,115 @@ static int acpi_processor_get_throttling(struct acpi_processor *pr) | |||
| 94 | return 0; | 308 | return 0; |
| 95 | } | 309 | } |
| 96 | 310 | ||
| 97 | int acpi_processor_set_throttling(struct acpi_processor *pr, int state) | 311 | static int acpi_read_throttling_status(struct acpi_processor_throttling |
| 312 | *throttling) | ||
| 313 | { | ||
| 314 | int value = -1; | ||
| 315 | switch (throttling->status_register.space_id) { | ||
| 316 | case ACPI_ADR_SPACE_SYSTEM_IO: | ||
| 317 | acpi_os_read_port((acpi_io_address) throttling->status_register. | ||
| 318 | address, &value, | ||
| 319 | (u32) throttling->status_register.bit_width * | ||
| 320 | 8); | ||
| 321 | break; | ||
| 322 | case ACPI_ADR_SPACE_FIXED_HARDWARE: | ||
| 323 | printk(KERN_ERR PREFIX | ||
| 324 | "HARDWARE addr space,NOT supported yet\n"); | ||
| 325 | break; | ||
| 326 | default: | ||
| 327 | printk(KERN_ERR PREFIX "Unknown addr space %d\n", | ||
| 328 | (u32) (throttling->status_register.space_id)); | ||
| 329 | } | ||
| 330 | return value; | ||
| 331 | } | ||
| 332 | |||
| 333 | static int acpi_write_throttling_state(struct acpi_processor_throttling | ||
| 334 | *throttling, int value) | ||
| 335 | { | ||
| 336 | int ret = -1; | ||
| 337 | |||
| 338 | switch (throttling->control_register.space_id) { | ||
| 339 | case ACPI_ADR_SPACE_SYSTEM_IO: | ||
| 340 | acpi_os_write_port((acpi_io_address) throttling-> | ||
| 341 | control_register.address, value, | ||
| 342 | (u32) throttling->control_register. | ||
| 343 | bit_width * 8); | ||
| 344 | ret = 0; | ||
| 345 | break; | ||
| 346 | case ACPI_ADR_SPACE_FIXED_HARDWARE: | ||
| 347 | printk(KERN_ERR PREFIX | ||
| 348 | "HARDWARE addr space,NOT supported yet\n"); | ||
| 349 | break; | ||
| 350 | default: | ||
| 351 | printk(KERN_ERR PREFIX "Unknown addr space %d\n", | ||
| 352 | (u32) (throttling->control_register.space_id)); | ||
| 353 | } | ||
| 354 | return ret; | ||
| 355 | } | ||
| 356 | |||
| 357 | static int acpi_get_throttling_state(struct acpi_processor *pr, int value) | ||
| 358 | { | ||
| 359 | int i; | ||
| 360 | |||
| 361 | for (i = 0; i < pr->throttling.state_count; i++) { | ||
| 362 | struct acpi_processor_tx_tss *tx = | ||
| 363 | (struct acpi_processor_tx_tss *)&(pr->throttling. | ||
| 364 | states_tss[i]); | ||
| 365 | if (tx->control == value) | ||
| 366 | break; | ||
| 367 | } | ||
| 368 | if (i > pr->throttling.state_count) | ||
| 369 | i = -1; | ||
| 370 | return i; | ||
| 371 | } | ||
| 372 | |||
| 373 | static int acpi_get_throttling_value(struct acpi_processor *pr, int state) | ||
| 374 | { | ||
| 375 | int value = -1; | ||
| 376 | if (state >= 0 && state <= pr->throttling.state_count) { | ||
| 377 | struct acpi_processor_tx_tss *tx = | ||
| 378 | (struct acpi_processor_tx_tss *)&(pr->throttling. | ||
| 379 | states_tss[state]); | ||
| 380 | value = tx->control; | ||
| 381 | } | ||
| 382 | return value; | ||
| 383 | } | ||
| 384 | |||
| 385 | static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr) | ||
| 386 | { | ||
| 387 | int state = 0; | ||
| 388 | u32 value = 0; | ||
| 389 | |||
| 390 | if (!pr) | ||
| 391 | return -EINVAL; | ||
| 392 | |||
| 393 | if (!pr->flags.throttling) | ||
| 394 | return -ENODEV; | ||
| 395 | |||
| 396 | pr->throttling.state = 0; | ||
| 397 | local_irq_disable(); | ||
| 398 | value = acpi_read_throttling_status(&pr->throttling); | ||
| 399 | if (value >= 0) { | ||
| 400 | state = acpi_get_throttling_state(pr, value); | ||
| 401 | pr->throttling.state = state; | ||
| 402 | } | ||
| 403 | local_irq_enable(); | ||
| 404 | |||
| 405 | return 0; | ||
| 406 | } | ||
| 407 | |||
| 408 | static int acpi_processor_get_throttling(struct acpi_processor *pr) | ||
| 409 | { | ||
| 410 | return pr->throttling.acpi_processor_get_throttling(pr); | ||
| 411 | } | ||
| 412 | |||
| 413 | static int acpi_processor_set_throttling_fadt(struct acpi_processor *pr, | ||
| 414 | int state) | ||
| 98 | { | 415 | { |
| 99 | u32 value = 0; | 416 | u32 value = 0; |
| 100 | u32 duty_mask = 0; | 417 | u32 duty_mask = 0; |
| 101 | u32 duty_value = 0; | 418 | u32 duty_value = 0; |
| 102 | 419 | ||
| 103 | |||
| 104 | if (!pr) | 420 | if (!pr) |
| 105 | return -EINVAL; | 421 | return -EINVAL; |
| 106 | 422 | ||
| @@ -113,6 +429,8 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state) | |||
| 113 | if (state == pr->throttling.state) | 429 | if (state == pr->throttling.state) |
| 114 | return 0; | 430 | return 0; |
| 115 | 431 | ||
| 432 | if (state < pr->throttling_platform_limit) | ||
| 433 | return -EPERM; | ||
| 116 | /* | 434 | /* |
| 117 | * Calculate the duty_value and duty_mask. | 435 | * Calculate the duty_value and duty_mask. |
| 118 | */ | 436 | */ |
| @@ -165,12 +483,51 @@ int acpi_processor_set_throttling(struct acpi_processor *pr, int state) | |||
| 165 | return 0; | 483 | return 0; |
| 166 | } | 484 | } |
| 167 | 485 | ||
| 486 | static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr, | ||
| 487 | int state) | ||
| 488 | { | ||
| 489 | u32 value = 0; | ||
| 490 | |||
| 491 | if (!pr) | ||
| 492 | return -EINVAL; | ||
| 493 | |||
| 494 | if ((state < 0) || (state > (pr->throttling.state_count - 1))) | ||
| 495 | return -EINVAL; | ||
| 496 | |||
| 497 | if (!pr->flags.throttling) | ||
| 498 | return -ENODEV; | ||
| 499 | |||
| 500 | if (state == pr->throttling.state) | ||
| 501 | return 0; | ||
| 502 | |||
| 503 | if (state < pr->throttling_platform_limit) | ||
| 504 | return -EPERM; | ||
| 505 | |||
| 506 | local_irq_disable(); | ||
| 507 | |||
| 508 | value = acpi_get_throttling_value(pr, state); | ||
| 509 | if (value >= 0) { | ||
| 510 | acpi_write_throttling_state(&pr->throttling, value); | ||
| 511 | pr->throttling.state = state; | ||
| 512 | } | ||
| 513 | local_irq_enable(); | ||
| 514 | |||
| 515 | return 0; | ||
| 516 | } | ||
| 517 | |||
| 518 | int acpi_processor_set_throttling(struct acpi_processor *pr, int state) | ||
| 519 | { | ||
| 520 | return pr->throttling.acpi_processor_set_throttling(pr, state); | ||
| 521 | } | ||
| 522 | |||
| 168 | int acpi_processor_get_throttling_info(struct acpi_processor *pr) | 523 | int acpi_processor_get_throttling_info(struct acpi_processor *pr) |
| 169 | { | 524 | { |
| 170 | int result = 0; | 525 | int result = 0; |
| 171 | int step = 0; | 526 | int step = 0; |
| 172 | int i = 0; | 527 | int i = 0; |
| 173 | 528 | int no_ptc = 0; | |
| 529 | int no_tss = 0; | ||
| 530 | int no_tsd = 0; | ||
| 174 | 531 | ||
| 175 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 532 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
| 176 | "pblk_address[0x%08x] duty_offset[%d] duty_width[%d]\n", | 533 | "pblk_address[0x%08x] duty_offset[%d] duty_width[%d]\n", |
| @@ -182,6 +539,21 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr) | |||
| 182 | return -EINVAL; | 539 | return -EINVAL; |
| 183 | 540 | ||
| 184 | /* TBD: Support ACPI 2.0 objects */ | 541 | /* TBD: Support ACPI 2.0 objects */ |
| 542 | no_ptc = acpi_processor_get_throttling_control(pr); | ||
| 543 | no_tss = acpi_processor_get_throttling_states(pr); | ||
| 544 | no_tsd = acpi_processor_get_tsd(pr); | ||
| 545 | |||
| 546 | if (no_ptc || no_tss) { | ||
| 547 | pr->throttling.acpi_processor_get_throttling = | ||
| 548 | &acpi_processor_get_throttling_fadt; | ||
| 549 | pr->throttling.acpi_processor_set_throttling = | ||
| 550 | &acpi_processor_set_throttling_fadt; | ||
| 551 | } else { | ||
| 552 | pr->throttling.acpi_processor_get_throttling = | ||
| 553 | &acpi_processor_get_throttling_ptc; | ||
| 554 | pr->throttling.acpi_processor_set_throttling = | ||
| 555 | &acpi_processor_set_throttling_ptc; | ||
| 556 | } | ||
| 185 | 557 | ||
| 186 | if (!pr->throttling.address) { | 558 | if (!pr->throttling.address) { |
| 187 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling register\n")); | 559 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling register\n")); |
| @@ -262,7 +634,6 @@ static int acpi_processor_throttling_seq_show(struct seq_file *seq, | |||
| 262 | int i = 0; | 634 | int i = 0; |
| 263 | int result = 0; | 635 | int result = 0; |
| 264 | 636 | ||
| 265 | |||
| 266 | if (!pr) | 637 | if (!pr) |
| 267 | goto end; | 638 | goto end; |
| 268 | 639 | ||
| @@ -280,15 +651,25 @@ static int acpi_processor_throttling_seq_show(struct seq_file *seq, | |||
| 280 | } | 651 | } |
| 281 | 652 | ||
| 282 | seq_printf(seq, "state count: %d\n" | 653 | seq_printf(seq, "state count: %d\n" |
| 283 | "active state: T%d\n", | 654 | "active state: T%d\n" |
| 284 | pr->throttling.state_count, pr->throttling.state); | 655 | "state available: T%d to T%d\n", |
| 656 | pr->throttling.state_count, pr->throttling.state, | ||
| 657 | pr->throttling_platform_limit, | ||
| 658 | pr->throttling.state_count - 1); | ||
| 285 | 659 | ||
| 286 | seq_puts(seq, "states:\n"); | 660 | seq_puts(seq, "states:\n"); |
| 287 | for (i = 0; i < pr->throttling.state_count; i++) | 661 | if (acpi_processor_get_throttling == acpi_processor_get_throttling_fadt) |
| 288 | seq_printf(seq, " %cT%d: %02d%%\n", | 662 | for (i = 0; i < pr->throttling.state_count; i++) |
| 289 | (i == pr->throttling.state ? '*' : ' '), i, | 663 | seq_printf(seq, " %cT%d: %02d%%\n", |
| 290 | (pr->throttling.states[i].performance ? pr-> | 664 | (i == pr->throttling.state ? '*' : ' '), i, |
| 291 | throttling.states[i].performance / 10 : 0)); | 665 | (pr->throttling.states[i].performance ? pr-> |
| 666 | throttling.states[i].performance / 10 : 0)); | ||
| 667 | else | ||
| 668 | for (i = 0; i < pr->throttling.state_count; i++) | ||
| 669 | seq_printf(seq, " %cT%d: %02d%%\n", | ||
| 670 | (i == pr->throttling.state ? '*' : ' '), i, | ||
| 671 | (int)pr->throttling.states_tss[i]. | ||
| 672 | freqpercentage); | ||
| 292 | 673 | ||
| 293 | end: | 674 | end: |
| 294 | return 0; | 675 | return 0; |
| @@ -301,7 +682,7 @@ static int acpi_processor_throttling_open_fs(struct inode *inode, | |||
| 301 | PDE(inode)->data); | 682 | PDE(inode)->data); |
| 302 | } | 683 | } |
| 303 | 684 | ||
| 304 | static ssize_t acpi_processor_write_throttling(struct file * file, | 685 | static ssize_t acpi_processor_write_throttling(struct file *file, |
| 305 | const char __user * buffer, | 686 | const char __user * buffer, |
| 306 | size_t count, loff_t * data) | 687 | size_t count, loff_t * data) |
| 307 | { | 688 | { |
| @@ -310,7 +691,6 @@ static ssize_t acpi_processor_write_throttling(struct file * file, | |||
| 310 | struct acpi_processor *pr = m->private; | 691 | struct acpi_processor *pr = m->private; |
| 311 | char state_string[12] = { '\0' }; | 692 | char state_string[12] = { '\0' }; |
| 312 | 693 | ||
| 313 | |||
| 314 | if (!pr || (count > sizeof(state_string) - 1)) | 694 | if (!pr || (count > sizeof(state_string) - 1)) |
| 315 | return -EINVAL; | 695 | return -EINVAL; |
| 316 | 696 | ||
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index c1bae106833c..974d00ccfe84 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c | |||
| @@ -127,7 +127,7 @@ static int acpi_sbs_resume(struct acpi_device *device); | |||
| 127 | static struct acpi_driver acpi_sbs_driver = { | 127 | static struct acpi_driver acpi_sbs_driver = { |
| 128 | .name = "sbs", | 128 | .name = "sbs", |
| 129 | .class = ACPI_SBS_CLASS, | 129 | .class = ACPI_SBS_CLASS, |
| 130 | .ids = ACPI_SBS_HID, | 130 | .ids = "ACPI0001,ACPI0005", |
| 131 | .ops = { | 131 | .ops = { |
| 132 | .add = acpi_sbs_add, | 132 | .add = acpi_sbs_add, |
| 133 | .remove = acpi_sbs_remove, | 133 | .remove = acpi_sbs_remove, |
| @@ -176,10 +176,8 @@ struct acpi_battery { | |||
| 176 | }; | 176 | }; |
| 177 | 177 | ||
| 178 | struct acpi_sbs { | 178 | struct acpi_sbs { |
| 179 | acpi_handle handle; | ||
| 180 | int base; | 179 | int base; |
| 181 | struct acpi_device *device; | 180 | struct acpi_device *device; |
| 182 | struct acpi_ec_smbus *smbus; | ||
| 183 | struct mutex mutex; | 181 | struct mutex mutex; |
| 184 | int sbsm_present; | 182 | int sbsm_present; |
| 185 | int sbsm_batteries_supported; | 183 | int sbsm_batteries_supported; |
| @@ -511,7 +509,7 @@ static int acpi_sbsm_get_info(struct acpi_sbs *sbs) | |||
| 511 | "acpi_sbs_read_word() failed")); | 509 | "acpi_sbs_read_word() failed")); |
| 512 | goto end; | 510 | goto end; |
| 513 | } | 511 | } |
| 514 | 512 | sbs->sbsm_present = 1; | |
| 515 | sbs->sbsm_batteries_supported = battery_system_info & 0x000f; | 513 | sbs->sbsm_batteries_supported = battery_system_info & 0x000f; |
| 516 | 514 | ||
| 517 | end: | 515 | end: |
| @@ -1630,13 +1628,12 @@ static int acpi_sbs_add(struct acpi_device *device) | |||
| 1630 | { | 1628 | { |
| 1631 | struct acpi_sbs *sbs = NULL; | 1629 | struct acpi_sbs *sbs = NULL; |
| 1632 | int result = 0, remove_result = 0; | 1630 | int result = 0, remove_result = 0; |
| 1633 | unsigned long sbs_obj; | ||
| 1634 | int id; | 1631 | int id; |
| 1635 | acpi_status status = AE_OK; | 1632 | acpi_status status = AE_OK; |
| 1636 | unsigned long val; | 1633 | unsigned long val; |
| 1637 | 1634 | ||
| 1638 | status = | 1635 | status = |
| 1639 | acpi_evaluate_integer(device->parent->handle, "_EC", NULL, &val); | 1636 | acpi_evaluate_integer(device->handle, "_EC", NULL, &val); |
| 1640 | if (ACPI_FAILURE(status)) { | 1637 | if (ACPI_FAILURE(status)) { |
| 1641 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Error obtaining _EC")); | 1638 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Error obtaining _EC")); |
| 1642 | return -EIO; | 1639 | return -EIO; |
| @@ -1653,7 +1650,7 @@ static int acpi_sbs_add(struct acpi_device *device) | |||
| 1653 | 1650 | ||
| 1654 | sbs_mutex_lock(sbs); | 1651 | sbs_mutex_lock(sbs); |
| 1655 | 1652 | ||
| 1656 | sbs->base = (val & 0xff00ull) >> 8; | 1653 | sbs->base = 0xff & (val >> 8); |
| 1657 | sbs->device = device; | 1654 | sbs->device = device; |
| 1658 | 1655 | ||
| 1659 | strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME); | 1656 | strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME); |
| @@ -1665,24 +1662,10 @@ static int acpi_sbs_add(struct acpi_device *device) | |||
| 1665 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_ac_add() failed")); | 1662 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_ac_add() failed")); |
| 1666 | goto end; | 1663 | goto end; |
| 1667 | } | 1664 | } |
| 1668 | status = acpi_evaluate_integer(device->handle, "_SBS", NULL, &sbs_obj); | ||
| 1669 | if (status) { | ||
| 1670 | ACPI_EXCEPTION((AE_INFO, status, | ||
| 1671 | "acpi_evaluate_integer() failed")); | ||
| 1672 | result = -EIO; | ||
| 1673 | goto end; | ||
| 1674 | } | ||
| 1675 | if (sbs_obj > 0) { | ||
| 1676 | result = acpi_sbsm_get_info(sbs); | ||
| 1677 | if (result) { | ||
| 1678 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
| 1679 | "acpi_sbsm_get_info() failed")); | ||
| 1680 | goto end; | ||
| 1681 | } | ||
| 1682 | sbs->sbsm_present = 1; | ||
| 1683 | } | ||
| 1684 | 1665 | ||
| 1685 | if (sbs->sbsm_present == 0) { | 1666 | acpi_sbsm_get_info(sbs); |
| 1667 | |||
| 1668 | if (!sbs->sbsm_present) { | ||
| 1686 | result = acpi_battery_add(sbs, 0); | 1669 | result = acpi_battery_add(sbs, 0); |
| 1687 | if (result) { | 1670 | if (result) { |
| 1688 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 1671 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, |
| @@ -1702,8 +1685,6 @@ static int acpi_sbs_add(struct acpi_device *device) | |||
| 1702 | } | 1685 | } |
| 1703 | } | 1686 | } |
| 1704 | 1687 | ||
| 1705 | sbs->handle = device->handle; | ||
| 1706 | |||
| 1707 | init_timer(&sbs->update_timer); | 1688 | init_timer(&sbs->update_timer); |
| 1708 | result = acpi_check_update_proc(sbs); | 1689 | result = acpi_check_update_proc(sbs); |
| 1709 | if (result) | 1690 | if (result) |
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index 42127c0d612c..3279e72a94f8 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c | |||
| @@ -210,11 +210,6 @@ static void acpi_hibernation_finish(void) | |||
| 210 | 210 | ||
| 211 | /* reset firmware waking vector */ | 211 | /* reset firmware waking vector */ |
| 212 | acpi_set_firmware_waking_vector((acpi_physical_address) 0); | 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 | static int acpi_hibernation_pre_restore(void) | 215 | static int acpi_hibernation_pre_restore(void) |
diff --git a/drivers/acpi/system.c b/drivers/acpi/system.c index 83a8d3097904..edee2806e37b 100644 --- a/drivers/acpi/system.c +++ b/drivers/acpi/system.c | |||
| @@ -39,15 +39,12 @@ ACPI_MODULE_NAME("system"); | |||
| 39 | 39 | ||
| 40 | #define ACPI_SYSTEM_CLASS "system" | 40 | #define ACPI_SYSTEM_CLASS "system" |
| 41 | #define ACPI_SYSTEM_DEVICE_NAME "System" | 41 | #define ACPI_SYSTEM_DEVICE_NAME "System" |
| 42 | #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 | * Make ACPICA version work as module param | 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 | int result; | 48 | int result; |
| 52 | 49 | ||
| 53 | result = sprintf(buffer, "%x", ACPI_CA_VERSION); | 50 | result = sprintf(buffer, "%x", ACPI_CA_VERSION); |
| @@ -58,9 +55,126 @@ static int param_get_acpica_version(char *buffer, struct kernel_param *kp) { | |||
| 58 | module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444); | 55 | module_param_call(acpica_version, NULL, param_get_acpica_version, NULL, 0444); |
| 59 | 56 | ||
| 60 | /* -------------------------------------------------------------------------- | 57 | /* -------------------------------------------------------------------------- |
| 58 | FS Interface (/sys) | ||
| 59 | -------------------------------------------------------------------------- */ | ||
| 60 | static LIST_HEAD(acpi_table_attr_list); | ||
| 61 | static struct kobject tables_kobj; | ||
| 62 | |||
| 63 | struct acpi_table_attr { | ||
| 64 | struct bin_attribute attr; | ||
| 65 | char name[8]; | ||
| 66 | int instance; | ||
| 67 | struct list_head node; | ||
| 68 | }; | ||
| 69 | |||
| 70 | static ssize_t acpi_table_show(struct kobject *kobj, | ||
| 71 | struct bin_attribute *bin_attr, char *buf, | ||
| 72 | loff_t offset, size_t count) | ||
| 73 | { | ||
| 74 | struct acpi_table_attr *table_attr = | ||
| 75 | container_of(bin_attr, struct acpi_table_attr, attr); | ||
| 76 | struct acpi_table_header *table_header = NULL; | ||
| 77 | acpi_status status; | ||
| 78 | ssize_t ret_count = count; | ||
| 79 | |||
| 80 | status = | ||
| 81 | acpi_get_table(table_attr->name, table_attr->instance, | ||
| 82 | &table_header); | ||
| 83 | if (ACPI_FAILURE(status)) | ||
| 84 | return -ENODEV; | ||
| 85 | |||
| 86 | if (offset >= table_header->length) { | ||
| 87 | ret_count = 0; | ||
| 88 | goto end; | ||
| 89 | } | ||
| 90 | |||
| 91 | if (offset + ret_count > table_header->length) | ||
| 92 | ret_count = table_header->length - offset; | ||
| 93 | |||
| 94 | memcpy(buf, ((char *)table_header) + offset, ret_count); | ||
| 95 | |||
| 96 | end: | ||
| 97 | return ret_count; | ||
| 98 | } | ||
| 99 | |||
| 100 | static void acpi_table_attr_init(struct acpi_table_attr *table_attr, | ||
| 101 | struct acpi_table_header *table_header) | ||
| 102 | { | ||
| 103 | struct acpi_table_header *header = NULL; | ||
| 104 | struct acpi_table_attr *attr = NULL; | ||
| 105 | |||
| 106 | memcpy(table_attr->name, table_header->signature, ACPI_NAME_SIZE); | ||
| 107 | |||
| 108 | list_for_each_entry(attr, &acpi_table_attr_list, node) { | ||
| 109 | if (!memcmp(table_header->signature, attr->name, | ||
| 110 | ACPI_NAME_SIZE)) | ||
| 111 | if (table_attr->instance < attr->instance) | ||
| 112 | table_attr->instance = attr->instance; | ||
| 113 | } | ||
| 114 | table_attr->instance++; | ||
| 115 | |||
| 116 | if (table_attr->instance > 1 || (table_attr->instance == 1 && | ||
| 117 | !acpi_get_table(table_header-> | ||
| 118 | signature, 2, | ||
| 119 | &header))) | ||
| 120 | sprintf(table_attr->name + 4, "%d", table_attr->instance); | ||
| 121 | |||
| 122 | table_attr->attr.size = 0; | ||
| 123 | table_attr->attr.read = acpi_table_show; | ||
| 124 | table_attr->attr.attr.name = table_attr->name; | ||
| 125 | table_attr->attr.attr.mode = 0444; | ||
| 126 | table_attr->attr.attr.owner = THIS_MODULE; | ||
| 127 | |||
| 128 | return; | ||
| 129 | } | ||
| 130 | |||
| 131 | static int acpi_system_sysfs_init(void) | ||
| 132 | { | ||
| 133 | struct acpi_table_attr *table_attr; | ||
| 134 | struct acpi_table_header *table_header = NULL; | ||
| 135 | int table_index = 0; | ||
| 136 | int result; | ||
| 137 | |||
| 138 | tables_kobj.parent = &acpi_subsys.kobj; | ||
| 139 | kobject_set_name(&tables_kobj, "tables"); | ||
| 140 | result = kobject_register(&tables_kobj); | ||
| 141 | if (result) | ||
| 142 | return result; | ||
| 143 | |||
| 144 | do { | ||
| 145 | result = acpi_get_table_by_index(table_index, &table_header); | ||
| 146 | if (!result) { | ||
| 147 | table_index++; | ||
| 148 | table_attr = NULL; | ||
| 149 | table_attr = | ||
| 150 | kzalloc(sizeof(struct acpi_table_attr), GFP_KERNEL); | ||
| 151 | if (!table_attr) | ||
| 152 | return -ENOMEM; | ||
| 153 | |||
| 154 | acpi_table_attr_init(table_attr, table_header); | ||
| 155 | result = | ||
| 156 | sysfs_create_bin_file(&tables_kobj, | ||
| 157 | &table_attr->attr); | ||
| 158 | if (result) { | ||
| 159 | kfree(table_attr); | ||
| 160 | return result; | ||
| 161 | } else | ||
| 162 | list_add_tail(&table_attr->node, | ||
| 163 | &acpi_table_attr_list); | ||
| 164 | } | ||
| 165 | } while (!result); | ||
| 166 | |||
| 167 | return 0; | ||
| 168 | } | ||
| 169 | |||
| 170 | /* -------------------------------------------------------------------------- | ||
| 61 | FS Interface (/proc) | 171 | FS Interface (/proc) |
| 62 | -------------------------------------------------------------------------- */ | 172 | -------------------------------------------------------------------------- */ |
| 63 | #ifdef CONFIG_ACPI_PROCFS | 173 | #ifdef CONFIG_ACPI_PROCFS |
| 174 | #define ACPI_SYSTEM_FILE_INFO "info" | ||
| 175 | #define ACPI_SYSTEM_FILE_EVENT "event" | ||
| 176 | #define ACPI_SYSTEM_FILE_DSDT "dsdt" | ||
| 177 | #define ACPI_SYSTEM_FILE_FADT "fadt" | ||
| 64 | 178 | ||
| 65 | static int acpi_system_read_info(struct seq_file *seq, void *offset) | 179 | static int acpi_system_read_info(struct seq_file *seq, void *offset) |
| 66 | { | 180 | { |
| @@ -80,7 +194,6 @@ static const struct file_operations acpi_system_info_ops = { | |||
| 80 | .llseek = seq_lseek, | 194 | .llseek = seq_lseek, |
| 81 | .release = single_release, | 195 | .release = single_release, |
| 82 | }; | 196 | }; |
| 83 | #endif | ||
| 84 | 197 | ||
| 85 | static ssize_t acpi_system_read_dsdt(struct file *, char __user *, size_t, | 198 | static ssize_t acpi_system_read_dsdt(struct file *, char __user *, size_t, |
| 86 | loff_t *); | 199 | loff_t *); |
| @@ -97,13 +210,11 @@ acpi_system_read_dsdt(struct file *file, | |||
| 97 | struct acpi_table_header *dsdt = NULL; | 210 | struct acpi_table_header *dsdt = NULL; |
| 98 | ssize_t res; | 211 | ssize_t res; |
| 99 | 212 | ||
| 100 | |||
| 101 | status = acpi_get_table(ACPI_SIG_DSDT, 1, &dsdt); | 213 | status = acpi_get_table(ACPI_SIG_DSDT, 1, &dsdt); |
| 102 | if (ACPI_FAILURE(status)) | 214 | if (ACPI_FAILURE(status)) |
| 103 | return -ENODEV; | 215 | return -ENODEV; |
| 104 | 216 | ||
| 105 | res = simple_read_from_buffer(buffer, count, ppos, | 217 | res = simple_read_from_buffer(buffer, count, ppos, dsdt, dsdt->length); |
| 106 | dsdt, dsdt->length); | ||
| 107 | 218 | ||
| 108 | return res; | 219 | return res; |
| 109 | } | 220 | } |
| @@ -123,28 +234,21 @@ acpi_system_read_fadt(struct file *file, | |||
| 123 | struct acpi_table_header *fadt = NULL; | 234 | struct acpi_table_header *fadt = NULL; |
| 124 | ssize_t res; | 235 | ssize_t res; |
| 125 | 236 | ||
| 126 | |||
| 127 | status = acpi_get_table(ACPI_SIG_FADT, 1, &fadt); | 237 | status = acpi_get_table(ACPI_SIG_FADT, 1, &fadt); |
| 128 | if (ACPI_FAILURE(status)) | 238 | if (ACPI_FAILURE(status)) |
| 129 | return -ENODEV; | 239 | return -ENODEV; |
| 130 | 240 | ||
| 131 | res = simple_read_from_buffer(buffer, count, ppos, | 241 | res = simple_read_from_buffer(buffer, count, ppos, fadt, fadt->length); |
| 132 | fadt, fadt->length); | ||
| 133 | 242 | ||
| 134 | return res; | 243 | return res; |
| 135 | } | 244 | } |
| 136 | 245 | ||
| 137 | static int __init acpi_system_init(void) | 246 | static int acpi_system_procfs_init(void) |
| 138 | { | 247 | { |
| 139 | struct proc_dir_entry *entry; | 248 | struct proc_dir_entry *entry; |
| 140 | int error = 0; | 249 | int error = 0; |
| 141 | char *name; | 250 | char *name; |
| 142 | 251 | ||
| 143 | |||
| 144 | if (acpi_disabled) | ||
| 145 | return 0; | ||
| 146 | |||
| 147 | #ifdef CONFIG_ACPI_PROCFS | ||
| 148 | /* 'info' [R] */ | 252 | /* 'info' [R] */ |
| 149 | name = ACPI_SYSTEM_FILE_INFO; | 253 | name = ACPI_SYSTEM_FILE_INFO; |
| 150 | entry = create_proc_entry(name, S_IRUGO, acpi_root_dir); | 254 | entry = create_proc_entry(name, S_IRUGO, acpi_root_dir); |
| @@ -153,7 +257,6 @@ static int __init acpi_system_init(void) | |||
| 153 | else { | 257 | else { |
| 154 | entry->proc_fops = &acpi_system_info_ops; | 258 | entry->proc_fops = &acpi_system_info_ops; |
| 155 | } | 259 | } |
| 156 | #endif | ||
| 157 | 260 | ||
| 158 | /* 'dsdt' [R] */ | 261 | /* 'dsdt' [R] */ |
| 159 | name = ACPI_SYSTEM_FILE_DSDT; | 262 | name = ACPI_SYSTEM_FILE_DSDT; |
| @@ -177,12 +280,32 @@ static int __init acpi_system_init(void) | |||
| 177 | Error: | 280 | Error: |
| 178 | remove_proc_entry(ACPI_SYSTEM_FILE_FADT, acpi_root_dir); | 281 | remove_proc_entry(ACPI_SYSTEM_FILE_FADT, acpi_root_dir); |
| 179 | remove_proc_entry(ACPI_SYSTEM_FILE_DSDT, acpi_root_dir); | 282 | remove_proc_entry(ACPI_SYSTEM_FILE_DSDT, acpi_root_dir); |
| 180 | #ifdef CONFIG_ACPI_PROCFS | ||
| 181 | remove_proc_entry(ACPI_SYSTEM_FILE_INFO, acpi_root_dir); | 283 | remove_proc_entry(ACPI_SYSTEM_FILE_INFO, acpi_root_dir); |
| 182 | #endif | ||
| 183 | 284 | ||
| 184 | error = -EFAULT; | 285 | error = -EFAULT; |
| 185 | goto Done; | 286 | goto Done; |
| 186 | } | 287 | } |
| 288 | #else | ||
| 289 | static int acpi_system_procfs_init(void) | ||
| 290 | { | ||
| 291 | return 0; | ||
| 292 | } | ||
| 293 | #endif | ||
| 294 | |||
| 295 | static int __init acpi_system_init(void) | ||
| 296 | { | ||
| 297 | int result = 0; | ||
| 298 | |||
| 299 | if (acpi_disabled) | ||
| 300 | return 0; | ||
| 301 | |||
| 302 | result = acpi_system_procfs_init(); | ||
| 303 | if (result) | ||
| 304 | return result; | ||
| 305 | |||
| 306 | result = acpi_system_sysfs_init(); | ||
| 307 | |||
| 308 | return result; | ||
| 309 | } | ||
| 187 | 310 | ||
| 188 | subsys_initcall(acpi_system_init); | 311 | subsys_initcall(acpi_system_init); |
diff --git a/drivers/acpi/tables/tbfadt.c b/drivers/acpi/tables/tbfadt.c index 1285e91474fb..002bb33003af 100644 --- a/drivers/acpi/tables/tbfadt.c +++ b/drivers/acpi/tables/tbfadt.c | |||
| @@ -211,14 +211,17 @@ void acpi_tb_parse_fadt(acpi_native_uint table_index, u8 flags) | |||
| 211 | * DESCRIPTION: Get a local copy of the FADT and convert it to a common format. | 211 | * DESCRIPTION: Get a local copy of the FADT and convert it to a common format. |
| 212 | * Performs validation on some important FADT fields. | 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 | void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) | 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). | 222 | * Check if the FADT is larger than the largest table that we expect |
| 221 | * Truncate the table, but make some noise. | 223 | * (the ACPI 2.0/3.0 version). If so, truncate the table, and issue |
| 224 | * a warning. | ||
| 222 | */ | 225 | */ |
| 223 | if (length > sizeof(struct acpi_table_fadt)) { | 226 | if (length > sizeof(struct acpi_table_fadt)) { |
| 224 | ACPI_WARNING((AE_INFO, | 227 | ACPI_WARNING((AE_INFO, |
| @@ -227,10 +230,12 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) | |||
| 227 | sizeof(struct acpi_table_fadt))); | 230 | sizeof(struct acpi_table_fadt))); |
| 228 | } | 231 | } |
| 229 | 232 | ||
| 230 | /* Copy the entire FADT locally. Zero first for tb_convert_fadt */ | 233 | /* Clear the entire local FADT */ |
| 231 | 234 | ||
| 232 | ACPI_MEMSET(&acpi_gbl_FADT, 0, sizeof(struct acpi_table_fadt)); | 235 | ACPI_MEMSET(&acpi_gbl_FADT, 0, sizeof(struct acpi_table_fadt)); |
| 233 | 236 | ||
| 237 | /* Copy the original FADT, up to sizeof (struct acpi_table_fadt) */ | ||
| 238 | |||
| 234 | ACPI_MEMCPY(&acpi_gbl_FADT, table, | 239 | ACPI_MEMCPY(&acpi_gbl_FADT, table, |
| 235 | ACPI_MIN(length, sizeof(struct acpi_table_fadt))); | 240 | ACPI_MIN(length, sizeof(struct acpi_table_fadt))); |
| 236 | 241 | ||
| @@ -251,7 +256,7 @@ void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) | |||
| 251 | * RETURN: None | 256 | * RETURN: None |
| 252 | * | 257 | * |
| 253 | * DESCRIPTION: Converts all versions of the FADT to a common internal format. | 258 | * DESCRIPTION: Converts all versions of the FADT to a common internal format. |
| 254 | * -> Expand all 32-bit addresses to 64-bit. | 259 | * Expand all 32-bit addresses to 64-bit. |
| 255 | * | 260 | * |
| 256 | * NOTE: acpi_gbl_FADT must be of size (struct acpi_table_fadt), | 261 | * NOTE: acpi_gbl_FADT must be of size (struct acpi_table_fadt), |
| 257 | * and must contain a copy of the actual FADT. | 262 | * and must contain a copy of the actual FADT. |
| @@ -292,8 +297,23 @@ static void acpi_tb_convert_fadt(void) | |||
| 292 | } | 297 | } |
| 293 | 298 | ||
| 294 | /* | 299 | /* |
| 295 | * Expand the 32-bit V1.0 addresses to the 64-bit "X" generic address | 300 | * For ACPI 1.0 FADTs (revision 1 or 2), ensure that reserved fields which |
| 296 | * structures as necessary. | 301 | * should be zero are indeed zero. This will workaround BIOSs that |
| 302 | * inadvertently place values in these fields. | ||
| 303 | * | ||
| 304 | * The ACPI 1.0 reserved fields that will be zeroed are the bytes located at | ||
| 305 | * offset 45, 55, 95, and the word located at offset 109, 110. | ||
| 306 | */ | ||
| 307 | if (acpi_gbl_FADT.header.revision < 3) { | ||
| 308 | acpi_gbl_FADT.preferred_profile = 0; | ||
| 309 | acpi_gbl_FADT.pstate_control = 0; | ||
| 310 | acpi_gbl_FADT.cst_control = 0; | ||
| 311 | acpi_gbl_FADT.boot_flags = 0; | ||
| 312 | } | ||
| 313 | |||
| 314 | /* | ||
| 315 | * Expand the ACPI 1.0 32-bit V1.0 addresses to the ACPI 2.0 64-bit "X" | ||
| 316 | * generic address structures as necessary. | ||
| 297 | */ | 317 | */ |
| 298 | for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { | 318 | for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { |
| 299 | target = | 319 | target = |
| @@ -349,18 +369,6 @@ static void acpi_tb_convert_fadt(void) | |||
| 349 | acpi_gbl_FADT.xpm1a_event_block.space_id; | 369 | acpi_gbl_FADT.xpm1a_event_block.space_id; |
| 350 | 370 | ||
| 351 | } | 371 | } |
| 352 | |||
| 353 | /* | ||
| 354 | * For ACPI 1.0 FADTs, ensure that reserved fields (which should be zero) | ||
| 355 | * are indeed zero. This will workaround BIOSs that inadvertently placed | ||
| 356 | * values in these fields. | ||
| 357 | */ | ||
| 358 | if (acpi_gbl_FADT.header.revision < 3) { | ||
| 359 | acpi_gbl_FADT.preferred_profile = 0; | ||
| 360 | acpi_gbl_FADT.pstate_control = 0; | ||
| 361 | acpi_gbl_FADT.cst_control = 0; | ||
| 362 | acpi_gbl_FADT.boot_flags = 0; | ||
| 363 | } | ||
| 364 | } | 372 | } |
| 365 | 373 | ||
| 366 | /****************************************************************************** | 374 | /****************************************************************************** |
diff --git a/drivers/acpi/utilities/uteval.c b/drivers/acpi/utilities/uteval.c index 8ec6f8e48138..f112af433e36 100644 --- a/drivers/acpi/utilities/uteval.c +++ b/drivers/acpi/utilities/uteval.c | |||
| @@ -62,16 +62,13 @@ acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc, | |||
| 62 | static char *acpi_interfaces_supported[] = { | 62 | static char *acpi_interfaces_supported[] = { |
| 63 | /* Operating System Vendor Strings */ | 63 | /* Operating System Vendor Strings */ |
| 64 | 64 | ||
| 65 | "Windows 2000", | 65 | "Windows 2000", /* Windows 2000 */ |
| 66 | "Windows 2001", | 66 | "Windows 2001", /* Windows XP */ |
| 67 | "Windows 2001 SP0", | 67 | "Windows 2001 SP1", /* Windows XP SP1 */ |
| 68 | "Windows 2001 SP1", | 68 | "Windows 2001 SP2", /* Windows XP SP2 */ |
| 69 | "Windows 2001 SP2", | 69 | "Windows 2001.1", /* Windows Server 2003 */ |
| 70 | "Windows 2001 SP3", | 70 | "Windows 2001.1 SP1", /* Windows Server 2003 SP1 - Added 03/2006 */ |
| 71 | "Windows 2001 SP4", | 71 | "Windows 2006", /* Windows Vista - Added 03/2006 */ |
| 72 | "Windows 2001.1", | ||
| 73 | "Windows 2001.1 SP1", /* Added 03/2006 */ | ||
| 74 | "Windows 2006", /* Added 03/2006 */ | ||
| 75 | 72 | ||
| 76 | /* Feature Group Strings */ | 73 | /* Feature Group Strings */ |
| 77 | 74 | ||
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 00d25b347255..5f014d3764c8 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | #include <linux/seq_file.h> | 33 | #include <linux/seq_file.h> |
| 34 | 34 | ||
| 35 | #include <linux/backlight.h> | 35 | #include <linux/backlight.h> |
| 36 | #include <linux/video_output.h> | ||
| 36 | #include <asm/uaccess.h> | 37 | #include <asm/uaccess.h> |
| 37 | 38 | ||
| 38 | #include <acpi/acpi_bus.h> | 39 | #include <acpi/acpi_bus.h> |
| @@ -169,6 +170,7 @@ struct acpi_video_device { | |||
| 169 | struct acpi_device *dev; | 170 | struct acpi_device *dev; |
| 170 | struct acpi_video_device_brightness *brightness; | 171 | struct acpi_video_device_brightness *brightness; |
| 171 | struct backlight_device *backlight; | 172 | struct backlight_device *backlight; |
| 173 | struct output_device *output_dev; | ||
| 172 | }; | 174 | }; |
| 173 | 175 | ||
| 174 | /* bus */ | 176 | /* bus */ |
| @@ -272,6 +274,10 @@ static int acpi_video_get_next_level(struct acpi_video_device *device, | |||
| 272 | u32 level_current, u32 event); | 274 | u32 level_current, u32 event); |
| 273 | static void acpi_video_switch_brightness(struct acpi_video_device *device, | 275 | static void acpi_video_switch_brightness(struct acpi_video_device *device, |
| 274 | int event); | 276 | int event); |
| 277 | static int acpi_video_device_get_state(struct acpi_video_device *device, | ||
| 278 | unsigned long *state); | ||
| 279 | static int acpi_video_output_get(struct output_device *od); | ||
| 280 | static int acpi_video_device_set_state(struct acpi_video_device *device, int state); | ||
| 275 | 281 | ||
| 276 | /*backlight device sysfs support*/ | 282 | /*backlight device sysfs support*/ |
| 277 | static int acpi_video_get_brightness(struct backlight_device *bd) | 283 | static int acpi_video_get_brightness(struct backlight_device *bd) |
| @@ -297,6 +303,28 @@ static struct backlight_ops acpi_backlight_ops = { | |||
| 297 | .update_status = acpi_video_set_brightness, | 303 | .update_status = acpi_video_set_brightness, |
| 298 | }; | 304 | }; |
| 299 | 305 | ||
| 306 | /*video output device sysfs support*/ | ||
| 307 | static int acpi_video_output_get(struct output_device *od) | ||
| 308 | { | ||
| 309 | unsigned long state; | ||
| 310 | struct acpi_video_device *vd = | ||
| 311 | (struct acpi_video_device *)class_get_devdata(&od->class_dev); | ||
| 312 | acpi_video_device_get_state(vd, &state); | ||
| 313 | return (int)state; | ||
| 314 | } | ||
| 315 | |||
| 316 | static int acpi_video_output_set(struct output_device *od) | ||
| 317 | { | ||
| 318 | unsigned long state = od->request_state; | ||
| 319 | struct acpi_video_device *vd= | ||
| 320 | (struct acpi_video_device *)class_get_devdata(&od->class_dev); | ||
| 321 | return acpi_video_device_set_state(vd, state); | ||
| 322 | } | ||
| 323 | |||
| 324 | static struct output_properties acpi_output_properties = { | ||
| 325 | .set_state = acpi_video_output_set, | ||
| 326 | .get_status = acpi_video_output_get, | ||
| 327 | }; | ||
| 300 | /* -------------------------------------------------------------------------- | 328 | /* -------------------------------------------------------------------------- |
| 301 | Video Management | 329 | Video Management |
| 302 | -------------------------------------------------------------------------- */ | 330 | -------------------------------------------------------------------------- */ |
| @@ -531,7 +559,6 @@ acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag) | |||
| 531 | 559 | ||
| 532 | static void acpi_video_device_find_cap(struct acpi_video_device *device) | 560 | static void acpi_video_device_find_cap(struct acpi_video_device *device) |
| 533 | { | 561 | { |
| 534 | acpi_integer status; | ||
| 535 | acpi_handle h_dummy1; | 562 | acpi_handle h_dummy1; |
| 536 | int i; | 563 | int i; |
| 537 | u32 max_level = 0; | 564 | u32 max_level = 0; |
| @@ -565,50 +592,55 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
| 565 | device->cap._DSS = 1; | 592 | device->cap._DSS = 1; |
| 566 | } | 593 | } |
| 567 | 594 | ||
| 568 | status = acpi_video_device_lcd_query_levels(device, &obj); | 595 | if (ACPI_SUCCESS(acpi_video_device_lcd_query_levels(device, &obj))) { |
| 569 | 596 | ||
| 570 | if (obj && obj->type == ACPI_TYPE_PACKAGE && obj->package.count >= 2) { | 597 | if (obj->package.count >= 2) { |
| 571 | int count = 0; | 598 | int count = 0; |
| 572 | union acpi_object *o; | 599 | union acpi_object *o; |
| 573 | 600 | ||
| 574 | br = kzalloc(sizeof(*br), GFP_KERNEL); | 601 | br = kzalloc(sizeof(*br), GFP_KERNEL); |
| 575 | if (!br) { | 602 | if (!br) { |
| 576 | printk(KERN_ERR "can't allocate memory\n"); | 603 | printk(KERN_ERR "can't allocate memory\n"); |
| 577 | } else { | ||
| 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 | if (br->levels[count] > max_level) | ||
| 592 | max_level = br->levels[count]; | ||
| 593 | count++; | ||
| 594 | } | ||
| 595 | out: | ||
| 596 | if (count < 2) { | ||
| 597 | kfree(br->levels); | ||
| 598 | kfree(br); | ||
| 599 | } else { | 604 | } else { |
| 600 | br->count = count; | 605 | br->levels = kmalloc(obj->package.count * |
| 601 | device->brightness = br; | 606 | sizeof *(br->levels), GFP_KERNEL); |
| 602 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 607 | if (!br->levels) |
| 603 | "found %d brightness levels\n", | 608 | goto out; |
| 604 | count)); | 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 | |||
| 619 | if (br->levels[count] > max_level) | ||
| 620 | max_level = br->levels[count]; | ||
| 621 | count++; | ||
| 622 | } | ||
| 623 | out: | ||
| 624 | if (count < 2) { | ||
| 625 | kfree(br->levels); | ||
| 626 | kfree(br); | ||
| 627 | } else { | ||
| 628 | br->count = count; | ||
| 629 | device->brightness = br; | ||
| 630 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
| 631 | "found %d brightness levels\n", | ||
| 632 | count)); | ||
| 633 | } | ||
| 605 | } | 634 | } |
| 606 | } | 635 | } |
| 636 | |||
| 637 | } else { | ||
| 638 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Could not query available LCD brightness level\n")); | ||
| 607 | } | 639 | } |
| 608 | 640 | ||
| 609 | kfree(obj); | 641 | kfree(obj); |
| 610 | 642 | ||
| 611 | if (device->cap._BCL && device->cap._BCM && device->cap._BQC){ | 643 | if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){ |
| 612 | unsigned long tmp; | 644 | unsigned long tmp; |
| 613 | static int count = 0; | 645 | static int count = 0; |
| 614 | char *name; | 646 | char *name; |
| @@ -626,6 +658,17 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
| 626 | 658 | ||
| 627 | kfree(name); | 659 | kfree(name); |
| 628 | } | 660 | } |
| 661 | if (device->cap._DCS && device->cap._DSS){ | ||
| 662 | static int count = 0; | ||
| 663 | char *name; | ||
| 664 | name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); | ||
| 665 | if (!name) | ||
| 666 | return; | ||
| 667 | sprintf(name, "acpi_video%d", count++); | ||
| 668 | device->output_dev = video_output_register(name, | ||
| 669 | NULL, device, &acpi_output_properties); | ||
| 670 | kfree(name); | ||
| 671 | } | ||
| 629 | return; | 672 | return; |
| 630 | } | 673 | } |
| 631 | 674 | ||
| @@ -1669,6 +1712,7 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device) | |||
| 1669 | ACPI_DEVICE_NOTIFY, | 1712 | ACPI_DEVICE_NOTIFY, |
| 1670 | acpi_video_device_notify); | 1713 | acpi_video_device_notify); |
| 1671 | backlight_device_unregister(device->backlight); | 1714 | backlight_device_unregister(device->backlight); |
| 1715 | video_output_unregister(device->output_dev); | ||
| 1672 | return 0; | 1716 | return 0; |
| 1673 | } | 1717 | } |
| 1674 | 1718 | ||
diff --git a/drivers/char/hvc_iseries.c b/drivers/char/hvc_iseries.c index b37f1d5a5be6..a08f8f981c11 100644 --- a/drivers/char/hvc_iseries.c +++ b/drivers/char/hvc_iseries.c | |||
| @@ -472,7 +472,7 @@ static void hvc_handle_event(struct HvLpEvent *event) | |||
| 472 | } | 472 | } |
| 473 | } | 473 | } |
| 474 | 474 | ||
| 475 | static int send_open(HvLpIndex remoteLp, void *sem) | 475 | static int __init send_open(HvLpIndex remoteLp, void *sem) |
| 476 | { | 476 | { |
| 477 | return HvCallEvent_signalLpEventFast(remoteLp, | 477 | return HvCallEvent_signalLpEventFast(remoteLp, |
| 478 | HvLpEvent_Type_VirtualIo, | 478 | HvLpEvent_Type_VirtualIo, |
| @@ -484,7 +484,7 @@ static int send_open(HvLpIndex remoteLp, void *sem) | |||
| 484 | 0, 0, 0, 0); | 484 | 0, 0, 0, 0); |
| 485 | } | 485 | } |
| 486 | 486 | ||
| 487 | static int hvc_vio_init(void) | 487 | static int __init hvc_vio_init(void) |
| 488 | { | 488 | { |
| 489 | atomic_t wait_flag; | 489 | atomic_t wait_flag; |
| 490 | int rc; | 490 | int rc; |
| @@ -552,14 +552,14 @@ static int hvc_vio_init(void) | |||
| 552 | } | 552 | } |
| 553 | module_init(hvc_vio_init); /* after drivers/char/hvc_console.c */ | 553 | module_init(hvc_vio_init); /* after drivers/char/hvc_console.c */ |
| 554 | 554 | ||
| 555 | static void hvc_vio_exit(void) | 555 | static void __exit hvc_vio_exit(void) |
| 556 | { | 556 | { |
| 557 | vio_unregister_driver(&hvc_vio_driver); | 557 | vio_unregister_driver(&hvc_vio_driver); |
| 558 | } | 558 | } |
| 559 | module_exit(hvc_vio_exit); | 559 | module_exit(hvc_vio_exit); |
| 560 | 560 | ||
| 561 | /* the device tree order defines our numbering */ | 561 | /* the device tree order defines our numbering */ |
| 562 | static int hvc_find_vtys(void) | 562 | static int __init hvc_find_vtys(void) |
| 563 | { | 563 | { |
| 564 | struct device_node *vty; | 564 | struct device_node *vty; |
| 565 | int num_found = 0; | 565 | int num_found = 0; |
diff --git a/drivers/char/hvc_rtas.c b/drivers/char/hvc_rtas.c index 4b97eaf18602..bb09413d5a21 100644 --- a/drivers/char/hvc_rtas.c +++ b/drivers/char/hvc_rtas.c | |||
| @@ -115,7 +115,7 @@ static void __exit hvc_rtas_exit(void) | |||
| 115 | module_exit(hvc_rtas_exit); | 115 | module_exit(hvc_rtas_exit); |
| 116 | 116 | ||
| 117 | /* This will happen prior to module init. There is no tty at this time? */ | 117 | /* This will happen prior to module init. There is no tty at this time? */ |
| 118 | static int hvc_rtas_console_init(void) | 118 | static int __init hvc_rtas_console_init(void) |
| 119 | { | 119 | { |
| 120 | rtascons_put_char_token = rtas_token("put-term-char"); | 120 | rtascons_put_char_token = rtas_token("put-term-char"); |
| 121 | if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE) | 121 | if (rtascons_put_char_token == RTAS_UNKNOWN_SERVICE) |
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c index 17f96e04266f..69d8866de783 100644 --- a/drivers/char/hvcs.c +++ b/drivers/char/hvcs.c | |||
| @@ -210,9 +210,9 @@ static struct ktermios hvcs_tty_termios = { | |||
| 210 | static int hvcs_parm_num_devs = -1; | 210 | static int hvcs_parm_num_devs = -1; |
| 211 | module_param(hvcs_parm_num_devs, int, 0); | 211 | module_param(hvcs_parm_num_devs, int, 0); |
| 212 | 212 | ||
| 213 | char hvcs_driver_name[] = "hvcs"; | 213 | static const char hvcs_driver_name[] = "hvcs"; |
| 214 | char hvcs_device_node[] = "hvcs"; | 214 | static const char hvcs_device_node[] = "hvcs"; |
| 215 | char hvcs_driver_string[] | 215 | static const char hvcs_driver_string[] |
| 216 | = "IBM hvcs (Hypervisor Virtual Console Server) Driver"; | 216 | = "IBM hvcs (Hypervisor Virtual Console Server) Driver"; |
| 217 | 217 | ||
| 218 | /* Status of partner info rescan triggered via sysfs. */ | 218 | /* Status of partner info rescan triggered via sysfs. */ |
| @@ -1092,7 +1092,7 @@ static int hvcs_enable_device(struct hvcs_struct *hvcsd, uint32_t unit_address, | |||
| 1092 | * NOTICE: Do NOT hold either the hvcs_struct.lock or hvcs_structs_lock when | 1092 | * NOTICE: Do NOT hold either the hvcs_struct.lock or hvcs_structs_lock when |
| 1093 | * calling this function or you will get deadlock. | 1093 | * calling this function or you will get deadlock. |
| 1094 | */ | 1094 | */ |
| 1095 | struct hvcs_struct *hvcs_get_by_index(int index) | 1095 | static struct hvcs_struct *hvcs_get_by_index(int index) |
| 1096 | { | 1096 | { |
| 1097 | struct hvcs_struct *hvcsd = NULL; | 1097 | struct hvcs_struct *hvcsd = NULL; |
| 1098 | unsigned long flags; | 1098 | unsigned long flags; |
diff --git a/drivers/kvm/Kconfig b/drivers/kvm/Kconfig index 2f661e5f0dae..6cecc396e040 100644 --- a/drivers/kvm/Kconfig +++ b/drivers/kvm/Kconfig | |||
| @@ -11,6 +11,7 @@ if VIRTUALIZATION | |||
| 11 | config KVM | 11 | config KVM |
| 12 | tristate "Kernel-based Virtual Machine (KVM) support" | 12 | tristate "Kernel-based Virtual Machine (KVM) support" |
| 13 | depends on X86 && EXPERIMENTAL | 13 | depends on X86 && EXPERIMENTAL |
| 14 | select ANON_INODES | ||
| 14 | ---help--- | 15 | ---help--- |
| 15 | Support hosting fully virtualized guest machines using hardware | 16 | Support hosting fully virtualized guest machines using hardware |
| 16 | virtualization extensions. You will need a fairly recent | 17 | virtualization extensions. You will need a fairly recent |
diff --git a/drivers/macintosh/rack-meter.c b/drivers/macintosh/rack-meter.c index 4177ff004753..2c21d4f25cc8 100644 --- a/drivers/macintosh/rack-meter.c +++ b/drivers/macintosh/rack-meter.c | |||
| @@ -30,7 +30,6 @@ | |||
| 30 | #include <asm/machdep.h> | 30 | #include <asm/machdep.h> |
| 31 | #include <asm/pmac_feature.h> | 31 | #include <asm/pmac_feature.h> |
| 32 | #include <asm/dbdma.h> | 32 | #include <asm/dbdma.h> |
| 33 | #include <asm/dbdma.h> | ||
| 34 | #include <asm/macio.h> | 33 | #include <asm/macio.h> |
| 35 | #include <asm/keylargo.h> | 34 | #include <asm/keylargo.h> |
| 36 | 35 | ||
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 1d516f24ba53..aaaa61ea4217 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig | |||
| @@ -150,6 +150,7 @@ config THINKPAD_ACPI | |||
| 150 | depends on X86 && ACPI | 150 | depends on X86 && ACPI |
| 151 | select BACKLIGHT_CLASS_DEVICE | 151 | select BACKLIGHT_CLASS_DEVICE |
| 152 | select HWMON | 152 | select HWMON |
| 153 | select NVRAM | ||
| 153 | ---help--- | 154 | ---help--- |
| 154 | This is a driver for the IBM and Lenovo ThinkPad laptops. It adds | 155 | This is a driver for the IBM and Lenovo ThinkPad laptops. It adds |
| 155 | support for Fn-Fx key combinations, Bluetooth control, video | 156 | support for Fn-Fx key combinations, Bluetooth control, video |
| @@ -196,4 +197,17 @@ config THINKPAD_ACPI_BAY | |||
| 196 | 197 | ||
| 197 | If you are not sure, say Y here. | 198 | If you are not sure, say Y here. |
| 198 | 199 | ||
| 200 | config THINKPAD_ACPI_INPUT_ENABLED | ||
| 201 | bool "Enable input layer support by default" | ||
| 202 | depends on THINKPAD_ACPI | ||
| 203 | default y | ||
| 204 | ---help--- | ||
| 205 | Enables hot key handling over the input layer by default. If unset, | ||
| 206 | the driver does not enable any hot key handling by default, and also | ||
| 207 | starts up with a mostly empty keymap. | ||
| 208 | |||
| 209 | If you are not sure, say Y here. Say N to retain the deprecated | ||
| 210 | behavior of ibm-acpi, and thinkpad-acpi for kernels up to 2.6.21. | ||
| 211 | |||
| 212 | |||
| 199 | endif # MISC_DEVICES | 213 | endif # MISC_DEVICES |
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c index 9623eaf4f89f..303e48ca0e8a 100644 --- a/drivers/misc/sony-laptop.c +++ b/drivers/misc/sony-laptop.c | |||
| @@ -142,43 +142,124 @@ struct sony_laptop_keypress { | |||
| 142 | int key; | 142 | int key; |
| 143 | }; | 143 | }; |
| 144 | 144 | ||
| 145 | /* Correspondance table between sonypi events and input layer events */ | 145 | /* Correspondance table between sonypi events |
| 146 | static struct { | 146 | * and input layer indexes in the keymap |
| 147 | int sonypiev; | 147 | */ |
| 148 | int inputev; | 148 | static int sony_laptop_input_index[] = { |
| 149 | } sony_laptop_inputkeys[] = { | 149 | -1, /* no event */ |
| 150 | { SONYPI_EVENT_CAPTURE_PRESSED, KEY_CAMERA }, | 150 | -1, /* SONYPI_EVENT_JOGDIAL_DOWN */ |
| 151 | { SONYPI_EVENT_FNKEY_ONLY, KEY_FN }, | 151 | -1, /* SONYPI_EVENT_JOGDIAL_UP */ |
| 152 | { SONYPI_EVENT_FNKEY_ESC, KEY_FN_ESC }, | 152 | -1, /* SONYPI_EVENT_JOGDIAL_DOWN_PRESSED */ |
| 153 | { SONYPI_EVENT_FNKEY_F1, KEY_FN_F1 }, | 153 | -1, /* SONYPI_EVENT_JOGDIAL_UP_PRESSED */ |
| 154 | { SONYPI_EVENT_FNKEY_F2, KEY_FN_F2 }, | 154 | -1, /* SONYPI_EVENT_JOGDIAL_PRESSED */ |
| 155 | { SONYPI_EVENT_FNKEY_F3, KEY_FN_F3 }, | 155 | -1, /* SONYPI_EVENT_JOGDIAL_RELEASED */ |
| 156 | { SONYPI_EVENT_FNKEY_F4, KEY_FN_F4 }, | 156 | 0, /* SONYPI_EVENT_CAPTURE_PRESSED */ |
| 157 | { SONYPI_EVENT_FNKEY_F5, KEY_FN_F5 }, | 157 | 1, /* SONYPI_EVENT_CAPTURE_RELEASED */ |
| 158 | { SONYPI_EVENT_FNKEY_F6, KEY_FN_F6 }, | 158 | 2, /* SONYPI_EVENT_CAPTURE_PARTIALPRESSED */ |
| 159 | { SONYPI_EVENT_FNKEY_F7, KEY_FN_F7 }, | 159 | 3, /* SONYPI_EVENT_CAPTURE_PARTIALRELEASED */ |
| 160 | { SONYPI_EVENT_FNKEY_F8, KEY_FN_F8 }, | 160 | 4, /* SONYPI_EVENT_FNKEY_ESC */ |
| 161 | { SONYPI_EVENT_FNKEY_F9, KEY_FN_F9 }, | 161 | 5, /* SONYPI_EVENT_FNKEY_F1 */ |
| 162 | { SONYPI_EVENT_FNKEY_F10, KEY_FN_F10 }, | 162 | 6, /* SONYPI_EVENT_FNKEY_F2 */ |
| 163 | { SONYPI_EVENT_FNKEY_F11, KEY_FN_F11 }, | 163 | 7, /* SONYPI_EVENT_FNKEY_F3 */ |
| 164 | { SONYPI_EVENT_FNKEY_F12, KEY_FN_F12 }, | 164 | 8, /* SONYPI_EVENT_FNKEY_F4 */ |
| 165 | { SONYPI_EVENT_FNKEY_1, KEY_FN_1 }, | 165 | 9, /* SONYPI_EVENT_FNKEY_F5 */ |
| 166 | { SONYPI_EVENT_FNKEY_2, KEY_FN_2 }, | 166 | 10, /* SONYPI_EVENT_FNKEY_F6 */ |
| 167 | { SONYPI_EVENT_FNKEY_D, KEY_FN_D }, | 167 | 11, /* SONYPI_EVENT_FNKEY_F7 */ |
| 168 | { SONYPI_EVENT_FNKEY_E, KEY_FN_E }, | 168 | 12, /* SONYPI_EVENT_FNKEY_F8 */ |
| 169 | { SONYPI_EVENT_FNKEY_F, KEY_FN_F }, | 169 | 13, /* SONYPI_EVENT_FNKEY_F9 */ |
| 170 | { SONYPI_EVENT_FNKEY_S, KEY_FN_S }, | 170 | 14, /* SONYPI_EVENT_FNKEY_F10 */ |
| 171 | { SONYPI_EVENT_FNKEY_B, KEY_FN_B }, | 171 | 15, /* SONYPI_EVENT_FNKEY_F11 */ |
| 172 | { SONYPI_EVENT_BLUETOOTH_PRESSED, KEY_BLUE }, | 172 | 16, /* SONYPI_EVENT_FNKEY_F12 */ |
| 173 | { SONYPI_EVENT_BLUETOOTH_ON, KEY_BLUE }, | 173 | 17, /* SONYPI_EVENT_FNKEY_1 */ |
| 174 | { SONYPI_EVENT_PKEY_P1, KEY_PROG1 }, | 174 | 18, /* SONYPI_EVENT_FNKEY_2 */ |
| 175 | { SONYPI_EVENT_PKEY_P2, KEY_PROG2 }, | 175 | 19, /* SONYPI_EVENT_FNKEY_D */ |
| 176 | { SONYPI_EVENT_PKEY_P3, KEY_PROG3 }, | 176 | 20, /* SONYPI_EVENT_FNKEY_E */ |
| 177 | { SONYPI_EVENT_BACK_PRESSED, KEY_BACK }, | 177 | 21, /* SONYPI_EVENT_FNKEY_F */ |
| 178 | { SONYPI_EVENT_HELP_PRESSED, KEY_HELP }, | 178 | 22, /* SONYPI_EVENT_FNKEY_S */ |
| 179 | { SONYPI_EVENT_ZOOM_PRESSED, KEY_ZOOM }, | 179 | 23, /* SONYPI_EVENT_FNKEY_B */ |
| 180 | { SONYPI_EVENT_THUMBPHRASE_PRESSED, BTN_THUMB }, | 180 | 24, /* SONYPI_EVENT_BLUETOOTH_PRESSED */ |
| 181 | { 0, 0 }, | 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 | /* release buttons after a short delay if pressed */ | 265 | /* release buttons after a short delay if pressed */ |
| @@ -202,7 +283,6 @@ static void sony_laptop_report_input_event(u8 event) | |||
| 202 | struct input_dev *jog_dev = sony_laptop_input.jog_dev; | 283 | struct input_dev *jog_dev = sony_laptop_input.jog_dev; |
| 203 | struct input_dev *key_dev = sony_laptop_input.key_dev; | 284 | struct input_dev *key_dev = sony_laptop_input.key_dev; |
| 204 | struct sony_laptop_keypress kp = { NULL }; | 285 | struct sony_laptop_keypress kp = { NULL }; |
| 205 | int i; | ||
| 206 | 286 | ||
| 207 | if (event == SONYPI_EVENT_FNKEY_RELEASED) { | 287 | if (event == SONYPI_EVENT_FNKEY_RELEASED) { |
| 208 | /* Nothing, not all VAIOs generate this event */ | 288 | /* Nothing, not all VAIOs generate this event */ |
| @@ -231,17 +311,22 @@ static void sony_laptop_report_input_event(u8 event) | |||
| 231 | break; | 311 | break; |
| 232 | 312 | ||
| 233 | default: | 313 | default: |
| 234 | for (i = 0; sony_laptop_inputkeys[i].sonypiev; i++) | 314 | if (event > ARRAY_SIZE (sony_laptop_input_keycode_map)) { |
| 235 | if (event == sony_laptop_inputkeys[i].sonypiev) { | 315 | dprintk("sony_laptop_report_input_event, event not known: %d\n", event); |
| 316 | break; | ||
| 317 | } | ||
| 318 | if (sony_laptop_input_index[event] != -1) { | ||
| 319 | kp.key = sony_laptop_input_keycode_map[sony_laptop_input_index[event]]; | ||
| 320 | if (kp.key != KEY_UNKNOWN) | ||
| 236 | kp.dev = key_dev; | 321 | kp.dev = key_dev; |
| 237 | kp.key = sony_laptop_inputkeys[i].inputev; | 322 | } |
| 238 | break; | ||
| 239 | } | ||
| 240 | break; | 323 | break; |
| 241 | } | 324 | } |
| 242 | 325 | ||
| 243 | if (kp.dev) { | 326 | if (kp.dev) { |
| 244 | input_report_key(kp.dev, kp.key, 1); | 327 | input_report_key(kp.dev, kp.key, 1); |
| 328 | /* we emit the scancode so we can always remap the key */ | ||
| 329 | input_event(kp.dev, EV_MSC, MSC_SCAN, event); | ||
| 245 | input_sync(kp.dev); | 330 | input_sync(kp.dev); |
| 246 | kfifo_put(sony_laptop_input.fifo, | 331 | kfifo_put(sony_laptop_input.fifo, |
| 247 | (unsigned char *)&kp, sizeof(kp)); | 332 | (unsigned char *)&kp, sizeof(kp)); |
| @@ -296,11 +381,18 @@ static int sony_laptop_setup_input(void) | |||
| 296 | key_dev->id.vendor = PCI_VENDOR_ID_SONY; | 381 | key_dev->id.vendor = PCI_VENDOR_ID_SONY; |
| 297 | 382 | ||
| 298 | /* Initialize the Input Drivers: special keys */ | 383 | /* Initialize the Input Drivers: special keys */ |
| 299 | key_dev->evbit[0] = BIT(EV_KEY); | 384 | set_bit(EV_KEY, key_dev->evbit); |
| 300 | for (i = 0; sony_laptop_inputkeys[i].sonypiev; i++) | 385 | set_bit(EV_MSC, key_dev->evbit); |
| 301 | if (sony_laptop_inputkeys[i].inputev) | 386 | set_bit(MSC_SCAN, key_dev->mscbit); |
| 302 | set_bit(sony_laptop_inputkeys[i].inputev, | 387 | key_dev->keycodesize = sizeof(sony_laptop_input_keycode_map[0]); |
| 303 | key_dev->keybit); | 388 | key_dev->keycodemax = ARRAY_SIZE(sony_laptop_input_keycode_map); |
| 389 | key_dev->keycode = &sony_laptop_input_keycode_map; | ||
| 390 | for (i = 0; i < ARRAY_SIZE(sony_laptop_input_keycode_map); i++) { | ||
| 391 | if (sony_laptop_input_keycode_map[i] != KEY_RESERVED) { | ||
| 392 | set_bit(sony_laptop_input_keycode_map[i], | ||
| 393 | key_dev->keybit); | ||
| 394 | } | ||
| 395 | } | ||
| 304 | 396 | ||
| 305 | error = input_register_device(key_dev); | 397 | error = input_register_device(key_dev); |
| 306 | if (error) | 398 | if (error) |
| @@ -487,6 +579,14 @@ SNC_HANDLE_NAMES(audiopower_set, "AZPW"); | |||
| 487 | SNC_HANDLE_NAMES(lanpower_get, "GLNP"); | 579 | SNC_HANDLE_NAMES(lanpower_get, "GLNP"); |
| 488 | SNC_HANDLE_NAMES(lanpower_set, "LNPW"); | 580 | SNC_HANDLE_NAMES(lanpower_set, "LNPW"); |
| 489 | 581 | ||
| 582 | SNC_HANDLE_NAMES(lidstate_get, "GLID"); | ||
| 583 | |||
| 584 | SNC_HANDLE_NAMES(indicatorlamp_get, "GILS"); | ||
| 585 | SNC_HANDLE_NAMES(indicatorlamp_set, "SILS"); | ||
| 586 | |||
| 587 | SNC_HANDLE_NAMES(gainbass_get, "GMGB"); | ||
| 588 | SNC_HANDLE_NAMES(gainbass_set, "CMGB"); | ||
| 589 | |||
| 490 | SNC_HANDLE_NAMES(PID_get, "GPID"); | 590 | SNC_HANDLE_NAMES(PID_get, "GPID"); |
| 491 | 591 | ||
| 492 | SNC_HANDLE_NAMES(CTR_get, "GCTR"); | 592 | SNC_HANDLE_NAMES(CTR_get, "GCTR"); |
| @@ -507,6 +607,12 @@ static struct sony_nc_value sony_nc_values[] = { | |||
| 507 | boolean_validate, 0), | 607 | boolean_validate, 0), |
| 508 | SNC_HANDLE(lanpower, snc_lanpower_get, snc_lanpower_set, | 608 | SNC_HANDLE(lanpower, snc_lanpower_get, snc_lanpower_set, |
| 509 | boolean_validate, 1), | 609 | boolean_validate, 1), |
| 610 | SNC_HANDLE(lidstate, snc_lidstate_get, NULL, | ||
| 611 | boolean_validate, 0), | ||
| 612 | SNC_HANDLE(indicatorlamp, snc_indicatorlamp_get, snc_indicatorlamp_set, | ||
| 613 | boolean_validate, 0), | ||
| 614 | SNC_HANDLE(gainbass, snc_gainbass_get, snc_gainbass_set, | ||
| 615 | boolean_validate, 0), | ||
| 510 | /* unknown methods */ | 616 | /* unknown methods */ |
| 511 | SNC_HANDLE(PID, snc_PID_get, NULL, NULL, 1), | 617 | SNC_HANDLE(PID, snc_PID_get, NULL, NULL, 1), |
| 512 | SNC_HANDLE(CTR, snc_CTR_get, snc_CTR_set, NULL, 1), | 618 | SNC_HANDLE(CTR, snc_CTR_get, snc_CTR_set, NULL, 1), |
| @@ -689,13 +795,116 @@ static struct backlight_ops sony_backlight_ops = { | |||
| 689 | }; | 795 | }; |
| 690 | 796 | ||
| 691 | /* | 797 | /* |
| 798 | * New SNC-only Vaios event mapping to driver known keys | ||
| 799 | */ | ||
| 800 | struct sony_nc_event { | ||
| 801 | u8 data; | ||
| 802 | u8 event; | ||
| 803 | }; | ||
| 804 | |||
| 805 | static struct sony_nc_event *sony_nc_events; | ||
| 806 | |||
| 807 | /* Vaio C* --maybe also FE*, N* and AR* ?-- special init sequence | ||
| 808 | * for Fn keys | ||
| 809 | */ | ||
| 810 | static int sony_nc_C_enable(struct dmi_system_id *id) | ||
| 811 | { | ||
| 812 | int result = 0; | ||
| 813 | |||
| 814 | printk(KERN_NOTICE DRV_PFX "detected %s\n", id->ident); | ||
| 815 | |||
| 816 | sony_nc_events = id->driver_data; | ||
| 817 | |||
| 818 | if (acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0x4, &result) < 0 | ||
| 819 | || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x2, &result) < 0 | ||
| 820 | || acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0x10, &result) < 0 | ||
| 821 | || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x0, &result) < 0 | ||
| 822 | || acpi_callsetfunc(sony_nc_acpi_handle, "SN03", 0x2, &result) < 0 | ||
| 823 | || acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x101, &result) < 0) { | ||
| 824 | printk(KERN_WARNING DRV_PFX "failed to initialize SNC, some " | ||
| 825 | "functionalities may be missing\n"); | ||
| 826 | return 1; | ||
| 827 | } | ||
| 828 | return 0; | ||
| 829 | } | ||
| 830 | |||
| 831 | static struct sony_nc_event sony_C_events[] = { | ||
| 832 | { 0x81, SONYPI_EVENT_FNKEY_F1 }, | ||
| 833 | { 0x01, SONYPI_EVENT_FNKEY_RELEASED }, | ||
| 834 | { 0x85, SONYPI_EVENT_FNKEY_F5 }, | ||
| 835 | { 0x05, SONYPI_EVENT_FNKEY_RELEASED }, | ||
| 836 | { 0x86, SONYPI_EVENT_FNKEY_F6 }, | ||
| 837 | { 0x06, SONYPI_EVENT_FNKEY_RELEASED }, | ||
| 838 | { 0x87, SONYPI_EVENT_FNKEY_F7 }, | ||
| 839 | { 0x07, SONYPI_EVENT_FNKEY_RELEASED }, | ||
| 840 | { 0x8A, SONYPI_EVENT_FNKEY_F10 }, | ||
| 841 | { 0x0A, SONYPI_EVENT_FNKEY_RELEASED }, | ||
| 842 | { 0x8C, SONYPI_EVENT_FNKEY_F12 }, | ||
| 843 | { 0x0C, SONYPI_EVENT_FNKEY_RELEASED }, | ||
| 844 | { 0, 0 }, | ||
| 845 | }; | ||
| 846 | |||
| 847 | /* SNC-only model map */ | ||
| 848 | struct dmi_system_id sony_nc_ids[] = { | ||
| 849 | { | ||
| 850 | .ident = "Sony Vaio FE Series", | ||
| 851 | .callback = sony_nc_C_enable, | ||
| 852 | .driver_data = sony_C_events, | ||
| 853 | .matches = { | ||
| 854 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | ||
| 855 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FE"), | ||
| 856 | }, | ||
| 857 | }, | ||
| 858 | { | ||
| 859 | .ident = "Sony Vaio C Series", | ||
| 860 | .callback = sony_nc_C_enable, | ||
| 861 | .driver_data = sony_C_events, | ||
| 862 | .matches = { | ||
| 863 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | ||
| 864 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-C"), | ||
| 865 | }, | ||
| 866 | }, | ||
| 867 | { } | ||
| 868 | }; | ||
| 869 | |||
| 870 | /* | ||
| 692 | * ACPI callbacks | 871 | * ACPI callbacks |
| 693 | */ | 872 | */ |
| 694 | static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) | 873 | static void sony_acpi_notify(acpi_handle handle, u32 event, void *data) |
| 695 | { | 874 | { |
| 696 | dprintk("sony_acpi_notify, event: %d\n", event); | 875 | struct sony_nc_event *evmap; |
| 697 | sony_laptop_report_input_event(event); | 876 | u32 ev = event; |
| 698 | acpi_bus_generate_event(sony_nc_acpi_device, 1, event); | 877 | int result; |
| 878 | |||
| 879 | if (ev == 0x92) { | ||
| 880 | /* read the key pressed from EC.GECR | ||
| 881 | * A call to SN07 with 0x0202 will do it as well respecting | ||
| 882 | * the current protocol on different OSes | ||
| 883 | * | ||
| 884 | * Note: the path for GECR may be | ||
| 885 | * \_SB.PCI0.LPCB.EC (C, FE, AR, N and friends) | ||
| 886 | * \_SB.PCI0.PIB.EC0 (VGN-FR notifications are sent directly, no GECR) | ||
| 887 | * | ||
| 888 | * TODO: we may want to do the same for the older GHKE -need | ||
| 889 | * dmi list- so this snippet may become one more callback. | ||
| 890 | */ | ||
| 891 | if (acpi_callsetfunc(handle, "SN07", 0x0202, &result) < 0) | ||
| 892 | dprintk("sony_acpi_notify, unable to decode event 0x%.2x\n", ev); | ||
| 893 | else | ||
| 894 | ev = result & 0xFF; | ||
| 895 | } | ||
| 896 | |||
| 897 | if (sony_nc_events) | ||
| 898 | for (evmap = sony_nc_events; evmap->event; evmap++) { | ||
| 899 | if (evmap->data == ev) { | ||
| 900 | ev = evmap->event; | ||
| 901 | break; | ||
| 902 | } | ||
| 903 | } | ||
| 904 | |||
| 905 | dprintk("sony_acpi_notify, event: 0x%.2x\n", ev); | ||
| 906 | sony_laptop_report_input_event(ev); | ||
| 907 | acpi_bus_generate_event(sony_nc_acpi_device, 1, ev); | ||
| 699 | } | 908 | } |
| 700 | 909 | ||
| 701 | static acpi_status sony_walk_callback(acpi_handle handle, u32 level, | 910 | static acpi_status sony_walk_callback(acpi_handle handle, u32 level, |
| @@ -732,6 +941,10 @@ static int sony_nc_resume(struct acpi_device *device) | |||
| 732 | break; | 941 | break; |
| 733 | } | 942 | } |
| 734 | } | 943 | } |
| 944 | |||
| 945 | /* re-initialize models with specific requirements */ | ||
| 946 | dmi_check_system(sony_nc_ids); | ||
| 947 | |||
| 735 | return 0; | 948 | return 0; |
| 736 | } | 949 | } |
| 737 | 950 | ||
| @@ -750,6 +963,15 @@ static int sony_nc_add(struct acpi_device *device) | |||
| 750 | 963 | ||
| 751 | sony_nc_acpi_handle = device->handle; | 964 | sony_nc_acpi_handle = device->handle; |
| 752 | 965 | ||
| 966 | /* read device status */ | ||
| 967 | result = acpi_bus_get_status(device); | ||
| 968 | /* bail IFF the above call was successful and the device is not present */ | ||
| 969 | if (!result && !device->status.present) { | ||
| 970 | dprintk("Device not present\n"); | ||
| 971 | result = -ENODEV; | ||
| 972 | goto outwalk; | ||
| 973 | } | ||
| 974 | |||
| 753 | if (debug) { | 975 | if (debug) { |
| 754 | status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_nc_acpi_handle, | 976 | status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_nc_acpi_handle, |
| 755 | 1, sony_walk_callback, NULL, NULL); | 977 | 1, sony_walk_callback, NULL, NULL); |
| @@ -760,6 +982,15 @@ static int sony_nc_add(struct acpi_device *device) | |||
| 760 | } | 982 | } |
| 761 | } | 983 | } |
| 762 | 984 | ||
| 985 | /* try to _INI the device if such method exists (ACPI spec 3.0-6.5.1 | ||
| 986 | * should be respected as we already checked for the device presence above */ | ||
| 987 | if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, METHOD_NAME__INI, &handle))) { | ||
| 988 | dprintk("Invoking _INI\n"); | ||
| 989 | if (ACPI_FAILURE(acpi_evaluate_object(sony_nc_acpi_handle, METHOD_NAME__INI, | ||
| 990 | NULL, NULL))) | ||
| 991 | dprintk("_INI Method failed\n"); | ||
| 992 | } | ||
| 993 | |||
| 763 | /* setup input devices and helper fifo */ | 994 | /* setup input devices and helper fifo */ |
| 764 | result = sony_laptop_setup_input(); | 995 | result = sony_laptop_setup_input(); |
| 765 | if (result) { | 996 | if (result) { |
| @@ -772,7 +1003,7 @@ static int sony_nc_add(struct acpi_device *device) | |||
| 772 | ACPI_DEVICE_NOTIFY, | 1003 | ACPI_DEVICE_NOTIFY, |
| 773 | sony_acpi_notify, NULL); | 1004 | sony_acpi_notify, NULL); |
| 774 | if (ACPI_FAILURE(status)) { | 1005 | if (ACPI_FAILURE(status)) { |
| 775 | printk(KERN_WARNING DRV_PFX "unable to install notify handler\n"); | 1006 | printk(KERN_WARNING DRV_PFX "unable to install notify handler (%u)\n", status); |
| 776 | result = -ENODEV; | 1007 | result = -ENODEV; |
| 777 | goto outinput; | 1008 | goto outinput; |
| 778 | } | 1009 | } |
| @@ -795,6 +1026,9 @@ static int sony_nc_add(struct acpi_device *device) | |||
| 795 | 1026 | ||
| 796 | } | 1027 | } |
| 797 | 1028 | ||
| 1029 | /* initialize models with specific requirements */ | ||
| 1030 | dmi_check_system(sony_nc_ids); | ||
| 1031 | |||
| 798 | result = sony_pf_add(); | 1032 | result = sony_pf_add(); |
| 799 | if (result) | 1033 | if (result) |
| 800 | goto outbacklight; | 1034 | goto outbacklight; |
| @@ -908,7 +1142,9 @@ static struct acpi_driver sony_nc_driver = { | |||
| 908 | #define SONYPI_DEVICE_TYPE2 0x00000002 | 1142 | #define SONYPI_DEVICE_TYPE2 0x00000002 |
| 909 | #define SONYPI_DEVICE_TYPE3 0x00000004 | 1143 | #define SONYPI_DEVICE_TYPE3 0x00000004 |
| 910 | 1144 | ||
| 911 | #define SONY_PIC_EV_MASK 0xff | 1145 | #define SONYPI_TYPE1_OFFSET 0x04 |
| 1146 | #define SONYPI_TYPE2_OFFSET 0x12 | ||
| 1147 | #define SONYPI_TYPE3_OFFSET 0x12 | ||
| 912 | 1148 | ||
| 913 | struct sony_pic_ioport { | 1149 | struct sony_pic_ioport { |
| 914 | struct acpi_resource_io io; | 1150 | struct acpi_resource_io io; |
| @@ -922,6 +1158,7 @@ struct sony_pic_irq { | |||
| 922 | 1158 | ||
| 923 | struct sony_pic_dev { | 1159 | struct sony_pic_dev { |
| 924 | int model; | 1160 | int model; |
| 1161 | u16 evport_offset; | ||
| 925 | u8 camera_power; | 1162 | u8 camera_power; |
| 926 | u8 bluetooth_power; | 1163 | u8 bluetooth_power; |
| 927 | u8 wwan_power; | 1164 | u8 wwan_power; |
| @@ -1999,20 +2236,17 @@ end: | |||
| 1999 | static irqreturn_t sony_pic_irq(int irq, void *dev_id) | 2236 | static irqreturn_t sony_pic_irq(int irq, void *dev_id) |
| 2000 | { | 2237 | { |
| 2001 | int i, j; | 2238 | int i, j; |
| 2002 | u32 port_val = 0; | ||
| 2003 | u8 ev = 0; | 2239 | u8 ev = 0; |
| 2004 | u8 data_mask = 0; | 2240 | u8 data_mask = 0; |
| 2005 | u8 device_event = 0; | 2241 | u8 device_event = 0; |
| 2006 | 2242 | ||
| 2007 | struct sony_pic_dev *dev = (struct sony_pic_dev *) dev_id; | 2243 | struct sony_pic_dev *dev = (struct sony_pic_dev *) dev_id; |
| 2008 | 2244 | ||
| 2009 | acpi_os_read_port(dev->cur_ioport->io.minimum, &port_val, | 2245 | ev = inb_p(dev->cur_ioport->io.minimum); |
| 2010 | dev->cur_ioport->io.address_length); | 2246 | data_mask = inb_p(dev->cur_ioport->io.minimum + dev->evport_offset); |
| 2011 | ev = port_val & SONY_PIC_EV_MASK; | ||
| 2012 | data_mask = 0xff & (port_val >> (dev->cur_ioport->io.address_length - 8)); | ||
| 2013 | 2247 | ||
| 2014 | dprintk("event (0x%.8x [%.2x] [%.2x]) at port 0x%.4x\n", | 2248 | dprintk("event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n", |
| 2015 | port_val, ev, data_mask, dev->cur_ioport->io.minimum); | 2249 | ev, data_mask, dev->cur_ioport->io.minimum, dev->evport_offset); |
| 2016 | 2250 | ||
| 2017 | if (ev == 0x00 || ev == 0xff) | 2251 | if (ev == 0x00 || ev == 0xff) |
| 2018 | return IRQ_HANDLED; | 2252 | return IRQ_HANDLED; |
| @@ -2103,6 +2337,20 @@ static int sony_pic_add(struct acpi_device *device) | |||
| 2103 | spic_dev.model = sony_pic_detect_device_type(); | 2337 | spic_dev.model = sony_pic_detect_device_type(); |
| 2104 | mutex_init(&spic_dev.lock); | 2338 | mutex_init(&spic_dev.lock); |
| 2105 | 2339 | ||
| 2340 | /* model specific characteristics */ | ||
| 2341 | switch(spic_dev.model) { | ||
| 2342 | case SONYPI_DEVICE_TYPE1: | ||
| 2343 | spic_dev.evport_offset = SONYPI_TYPE1_OFFSET; | ||
| 2344 | break; | ||
| 2345 | case SONYPI_DEVICE_TYPE3: | ||
| 2346 | spic_dev.evport_offset = SONYPI_TYPE3_OFFSET; | ||
| 2347 | break; | ||
| 2348 | case SONYPI_DEVICE_TYPE2: | ||
| 2349 | default: | ||
| 2350 | spic_dev.evport_offset = SONYPI_TYPE2_OFFSET; | ||
| 2351 | break; | ||
| 2352 | } | ||
| 2353 | |||
| 2106 | /* read _PRS resources */ | 2354 | /* read _PRS resources */ |
| 2107 | result = sony_pic_possible_resources(device); | 2355 | result = sony_pic_possible_resources(device); |
| 2108 | if (result) { | 2356 | if (result) { |
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 95c0b96e83f2..f15a58f7403f 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c | |||
| @@ -21,8 +21,8 @@ | |||
| 21 | * 02110-1301, USA. | 21 | * 02110-1301, USA. |
| 22 | */ | 22 | */ |
| 23 | 23 | ||
| 24 | #define IBM_VERSION "0.14" | 24 | #define IBM_VERSION "0.15" |
| 25 | #define TPACPI_SYSFS_VERSION 0x000100 | 25 | #define TPACPI_SYSFS_VERSION 0x010000 |
| 26 | 26 | ||
| 27 | /* | 27 | /* |
| 28 | * Changelog: | 28 | * Changelog: |
| @@ -92,6 +92,29 @@ MODULE_LICENSE("GPL"); | |||
| 92 | /* Please remove this in year 2009 */ | 92 | /* Please remove this in year 2009 */ |
| 93 | MODULE_ALIAS("ibm_acpi"); | 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 | #define __unused __attribute__ ((unused)) | 118 | #define __unused __attribute__ ((unused)) |
| 96 | 119 | ||
| 97 | /**************************************************************************** | 120 | /**************************************************************************** |
| @@ -106,7 +129,7 @@ MODULE_ALIAS("ibm_acpi"); | |||
| 106 | * ACPI basic handles | 129 | * ACPI basic handles |
| 107 | */ | 130 | */ |
| 108 | 131 | ||
| 109 | static acpi_handle root_handle = NULL; | 132 | static acpi_handle root_handle; |
| 110 | 133 | ||
| 111 | #define IBM_HANDLE(object, parent, paths...) \ | 134 | #define IBM_HANDLE(object, parent, paths...) \ |
| 112 | static acpi_handle object##_handle; \ | 135 | static acpi_handle object##_handle; \ |
| @@ -487,19 +510,36 @@ static char *next_cmd(char **cmds) | |||
| 487 | /**************************************************************************** | 510 | /**************************************************************************** |
| 488 | **************************************************************************** | 511 | **************************************************************************** |
| 489 | * | 512 | * |
| 490 | * Device model: hwmon and platform | 513 | * Device model: input, hwmon and platform |
| 491 | * | 514 | * |
| 492 | **************************************************************************** | 515 | **************************************************************************** |
| 493 | ****************************************************************************/ | 516 | ****************************************************************************/ |
| 494 | 517 | ||
| 495 | static struct platform_device *tpacpi_pdev = NULL; | 518 | static struct platform_device *tpacpi_pdev; |
| 496 | static struct class_device *tpacpi_hwmon = NULL; | 519 | static struct class_device *tpacpi_hwmon; |
| 520 | static struct input_dev *tpacpi_inputdev; | ||
| 521 | |||
| 522 | |||
| 523 | static int tpacpi_resume_handler(struct platform_device *pdev) | ||
| 524 | { | ||
| 525 | struct ibm_struct *ibm, *itmp; | ||
| 526 | |||
| 527 | list_for_each_entry_safe(ibm, itmp, | ||
| 528 | &tpacpi_all_drivers, | ||
| 529 | all_drivers) { | ||
| 530 | if (ibm->resume) | ||
| 531 | (ibm->resume)(); | ||
| 532 | } | ||
| 533 | |||
| 534 | return 0; | ||
| 535 | } | ||
| 497 | 536 | ||
| 498 | static struct platform_driver tpacpi_pdriver = { | 537 | static struct platform_driver tpacpi_pdriver = { |
| 499 | .driver = { | 538 | .driver = { |
| 500 | .name = IBM_DRVR_NAME, | 539 | .name = IBM_DRVR_NAME, |
| 501 | .owner = THIS_MODULE, | 540 | .owner = THIS_MODULE, |
| 502 | }, | 541 | }, |
| 542 | .resume = tpacpi_resume_handler, | ||
| 503 | }; | 543 | }; |
| 504 | 544 | ||
| 505 | 545 | ||
| @@ -677,9 +717,19 @@ static int __init thinkpad_acpi_driver_init(struct ibm_init_struct *iibm) | |||
| 677 | printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION); | 717 | printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION); |
| 678 | printk(IBM_INFO "%s\n", IBM_URL); | 718 | printk(IBM_INFO "%s\n", IBM_URL); |
| 679 | 719 | ||
| 680 | if (ibm_thinkpad_ec_found) | 720 | printk(IBM_INFO "ThinkPad BIOS %s, EC %s\n", |
| 681 | printk(IBM_INFO "ThinkPad EC firmware %s\n", | 721 | (thinkpad_id.bios_version_str) ? |
| 682 | ibm_thinkpad_ec_found); | 722 | thinkpad_id.bios_version_str : "unknown", |
| 723 | (thinkpad_id.ec_version_str) ? | ||
| 724 | thinkpad_id.ec_version_str : "unknown"); | ||
| 725 | |||
| 726 | if (thinkpad_id.vendor && thinkpad_id.model_str) | ||
| 727 | printk(IBM_INFO "%s %s\n", | ||
| 728 | (thinkpad_id.vendor == PCI_VENDOR_ID_IBM) ? | ||
| 729 | "IBM" : ((thinkpad_id.vendor == | ||
| 730 | PCI_VENDOR_ID_LENOVO) ? | ||
| 731 | "Lenovo" : "Unknown vendor"), | ||
| 732 | thinkpad_id.model_str); | ||
| 683 | 733 | ||
| 684 | return 0; | 734 | return 0; |
| 685 | } | 735 | } |
| @@ -704,16 +754,28 @@ static struct ibm_struct thinkpad_acpi_driver_data = { | |||
| 704 | */ | 754 | */ |
| 705 | 755 | ||
| 706 | static int hotkey_orig_status; | 756 | static int hotkey_orig_status; |
| 707 | static int hotkey_orig_mask; | 757 | static u32 hotkey_orig_mask; |
| 758 | static u32 hotkey_all_mask; | ||
| 759 | static u32 hotkey_reserved_mask; | ||
| 760 | |||
| 761 | static u16 *hotkey_keycode_map; | ||
| 708 | 762 | ||
| 709 | static struct attribute_set *hotkey_dev_attributes = NULL; | 763 | static struct attribute_set *hotkey_dev_attributes; |
| 764 | |||
| 765 | static int hotkey_get_wlsw(int *status) | ||
| 766 | { | ||
| 767 | if (!acpi_evalf(hkey_handle, status, "WLSW", "d")) | ||
| 768 | return -EIO; | ||
| 769 | return 0; | ||
| 770 | } | ||
| 710 | 771 | ||
| 711 | /* sysfs hotkey enable ------------------------------------------------- */ | 772 | /* sysfs hotkey enable ------------------------------------------------- */ |
| 712 | static ssize_t hotkey_enable_show(struct device *dev, | 773 | static ssize_t hotkey_enable_show(struct device *dev, |
| 713 | struct device_attribute *attr, | 774 | struct device_attribute *attr, |
| 714 | char *buf) | 775 | char *buf) |
| 715 | { | 776 | { |
| 716 | int res, status, mask; | 777 | int res, status; |
| 778 | u32 mask; | ||
| 717 | 779 | ||
| 718 | res = hotkey_get(&status, &mask); | 780 | res = hotkey_get(&status, &mask); |
| 719 | if (res) | 781 | if (res) |
| @@ -727,7 +789,8 @@ static ssize_t hotkey_enable_store(struct device *dev, | |||
| 727 | const char *buf, size_t count) | 789 | const char *buf, size_t count) |
| 728 | { | 790 | { |
| 729 | unsigned long t; | 791 | unsigned long t; |
| 730 | int res, status, mask; | 792 | int res, status; |
| 793 | u32 mask; | ||
| 731 | 794 | ||
| 732 | if (parse_strtoul(buf, 1, &t)) | 795 | if (parse_strtoul(buf, 1, &t)) |
| 733 | return -EINVAL; | 796 | return -EINVAL; |
| @@ -748,13 +811,14 @@ static ssize_t hotkey_mask_show(struct device *dev, | |||
| 748 | struct device_attribute *attr, | 811 | struct device_attribute *attr, |
| 749 | char *buf) | 812 | char *buf) |
| 750 | { | 813 | { |
| 751 | int res, status, mask; | 814 | int res, status; |
| 815 | u32 mask; | ||
| 752 | 816 | ||
| 753 | res = hotkey_get(&status, &mask); | 817 | res = hotkey_get(&status, &mask); |
| 754 | if (res) | 818 | if (res) |
| 755 | return res; | 819 | return res; |
| 756 | 820 | ||
| 757 | return snprintf(buf, PAGE_SIZE, "0x%04x\n", mask); | 821 | return snprintf(buf, PAGE_SIZE, "0x%08x\n", mask); |
| 758 | } | 822 | } |
| 759 | 823 | ||
| 760 | static ssize_t hotkey_mask_store(struct device *dev, | 824 | static ssize_t hotkey_mask_store(struct device *dev, |
| @@ -762,9 +826,10 @@ static ssize_t hotkey_mask_store(struct device *dev, | |||
| 762 | const char *buf, size_t count) | 826 | const char *buf, size_t count) |
| 763 | { | 827 | { |
| 764 | unsigned long t; | 828 | unsigned long t; |
| 765 | int res, status, mask; | 829 | int res, status; |
| 830 | u32 mask; | ||
| 766 | 831 | ||
| 767 | if (parse_strtoul(buf, 0xffff, &t)) | 832 | if (parse_strtoul(buf, 0xffffffffUL, &t)) |
| 768 | return -EINVAL; | 833 | return -EINVAL; |
| 769 | 834 | ||
| 770 | res = hotkey_get(&status, &mask); | 835 | res = hotkey_get(&status, &mask); |
| @@ -794,26 +859,123 @@ static ssize_t hotkey_bios_mask_show(struct device *dev, | |||
| 794 | struct device_attribute *attr, | 859 | struct device_attribute *attr, |
| 795 | char *buf) | 860 | char *buf) |
| 796 | { | 861 | { |
| 797 | return snprintf(buf, PAGE_SIZE, "0x%04x\n", hotkey_orig_mask); | 862 | return snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_orig_mask); |
| 798 | } | 863 | } |
| 799 | 864 | ||
| 800 | static struct device_attribute dev_attr_hotkey_bios_mask = | 865 | static struct device_attribute dev_attr_hotkey_bios_mask = |
| 801 | __ATTR(hotkey_bios_mask, S_IRUGO, hotkey_bios_mask_show, NULL); | 866 | __ATTR(hotkey_bios_mask, S_IRUGO, hotkey_bios_mask_show, NULL); |
| 802 | 867 | ||
| 868 | /* sysfs hotkey all_mask ----------------------------------------------- */ | ||
| 869 | static ssize_t hotkey_all_mask_show(struct device *dev, | ||
| 870 | struct device_attribute *attr, | ||
| 871 | char *buf) | ||
| 872 | { | ||
| 873 | return snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_all_mask); | ||
| 874 | } | ||
| 875 | |||
| 876 | static struct device_attribute dev_attr_hotkey_all_mask = | ||
| 877 | __ATTR(hotkey_all_mask, S_IRUGO, hotkey_all_mask_show, NULL); | ||
| 878 | |||
| 879 | /* sysfs hotkey recommended_mask --------------------------------------- */ | ||
| 880 | static ssize_t hotkey_recommended_mask_show(struct device *dev, | ||
| 881 | struct device_attribute *attr, | ||
| 882 | char *buf) | ||
| 883 | { | ||
| 884 | return snprintf(buf, PAGE_SIZE, "0x%08x\n", | ||
| 885 | hotkey_all_mask & ~hotkey_reserved_mask); | ||
| 886 | } | ||
| 887 | |||
| 888 | static struct device_attribute dev_attr_hotkey_recommended_mask = | ||
| 889 | __ATTR(hotkey_recommended_mask, S_IRUGO, | ||
| 890 | hotkey_recommended_mask_show, NULL); | ||
| 891 | |||
| 892 | /* sysfs hotkey radio_sw ----------------------------------------------- */ | ||
| 893 | static ssize_t hotkey_radio_sw_show(struct device *dev, | ||
| 894 | struct device_attribute *attr, | ||
| 895 | char *buf) | ||
| 896 | { | ||
| 897 | int res, s; | ||
| 898 | res = hotkey_get_wlsw(&s); | ||
| 899 | if (res < 0) | ||
| 900 | return res; | ||
| 901 | |||
| 902 | return snprintf(buf, PAGE_SIZE, "%d\n", !!s); | ||
| 903 | } | ||
| 904 | |||
| 905 | static struct device_attribute dev_attr_hotkey_radio_sw = | ||
| 906 | __ATTR(hotkey_radio_sw, S_IRUGO, hotkey_radio_sw_show, NULL); | ||
| 907 | |||
| 803 | /* --------------------------------------------------------------------- */ | 908 | /* --------------------------------------------------------------------- */ |
| 804 | 909 | ||
| 805 | static struct attribute *hotkey_mask_attributes[] = { | 910 | static struct attribute *hotkey_mask_attributes[] = { |
| 806 | &dev_attr_hotkey_mask.attr, | 911 | &dev_attr_hotkey_mask.attr, |
| 807 | &dev_attr_hotkey_bios_enabled.attr, | 912 | &dev_attr_hotkey_bios_enabled.attr, |
| 808 | &dev_attr_hotkey_bios_mask.attr, | 913 | &dev_attr_hotkey_bios_mask.attr, |
| 914 | &dev_attr_hotkey_all_mask.attr, | ||
| 915 | &dev_attr_hotkey_recommended_mask.attr, | ||
| 809 | }; | 916 | }; |
| 810 | 917 | ||
| 811 | static int __init hotkey_init(struct ibm_init_struct *iibm) | 918 | static int __init hotkey_init(struct ibm_init_struct *iibm) |
| 812 | { | 919 | { |
| 813 | int res; | 920 | |
| 921 | static u16 ibm_keycode_map[] __initdata = { | ||
| 922 | /* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */ | ||
| 923 | KEY_FN_F1, KEY_FN_F2, KEY_COFFEE, KEY_SLEEP, | ||
| 924 | KEY_WLAN, KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8, | ||
| 925 | KEY_FN_F9, KEY_FN_F10, KEY_FN_F11, KEY_SUSPEND, | ||
| 926 | /* Scan codes 0x0C to 0x0F: Other ACPI HKEY hot keys */ | ||
| 927 | KEY_UNKNOWN, /* 0x0C: FN+BACKSPACE */ | ||
| 928 | KEY_UNKNOWN, /* 0x0D: FN+INSERT */ | ||
| 929 | KEY_UNKNOWN, /* 0x0E: FN+DELETE */ | ||
| 930 | KEY_RESERVED, /* 0x0F: FN+HOME (brightness up) */ | ||
| 931 | /* Scan codes 0x10 to 0x1F: Extended ACPI HKEY hot keys */ | ||
| 932 | KEY_RESERVED, /* 0x10: FN+END (brightness down) */ | ||
| 933 | KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */ | ||
| 934 | KEY_UNKNOWN, /* 0x12: FN+PGDOWN */ | ||
| 935 | KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */ | ||
| 936 | KEY_RESERVED, /* 0x14: VOLUME UP */ | ||
| 937 | KEY_RESERVED, /* 0x15: VOLUME DOWN */ | ||
| 938 | KEY_RESERVED, /* 0x16: MUTE */ | ||
| 939 | KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */ | ||
| 940 | /* (assignments unknown, please report if found) */ | ||
| 941 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, | ||
| 942 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, | ||
| 943 | }; | ||
| 944 | static u16 lenovo_keycode_map[] __initdata = { | ||
| 945 | /* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */ | ||
| 946 | KEY_FN_F1, KEY_COFFEE, KEY_BATTERY, KEY_SLEEP, | ||
| 947 | KEY_WLAN, KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8, | ||
| 948 | KEY_FN_F9, KEY_FN_F10, KEY_FN_F11, KEY_SUSPEND, | ||
| 949 | /* Scan codes 0x0C to 0x0F: Other ACPI HKEY hot keys */ | ||
| 950 | KEY_UNKNOWN, /* 0x0C: FN+BACKSPACE */ | ||
| 951 | KEY_UNKNOWN, /* 0x0D: FN+INSERT */ | ||
| 952 | KEY_UNKNOWN, /* 0x0E: FN+DELETE */ | ||
| 953 | KEY_BRIGHTNESSUP, /* 0x0F: FN+HOME (brightness up) */ | ||
| 954 | /* Scan codes 0x10 to 0x1F: Extended ACPI HKEY hot keys */ | ||
| 955 | KEY_BRIGHTNESSDOWN, /* 0x10: FN+END (brightness down) */ | ||
| 956 | KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */ | ||
| 957 | KEY_UNKNOWN, /* 0x12: FN+PGDOWN */ | ||
| 958 | KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */ | ||
| 959 | KEY_RESERVED, /* 0x14: VOLUME UP */ | ||
| 960 | KEY_RESERVED, /* 0x15: VOLUME DOWN */ | ||
| 961 | KEY_RESERVED, /* 0x16: MUTE */ | ||
| 962 | KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */ | ||
| 963 | /* (assignments unknown, please report if found) */ | ||
| 964 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, | ||
| 965 | KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, | ||
| 966 | }; | ||
| 967 | |||
| 968 | #define TPACPI_HOTKEY_MAP_LEN ARRAY_SIZE(ibm_keycode_map) | ||
| 969 | #define TPACPI_HOTKEY_MAP_SIZE sizeof(ibm_keycode_map) | ||
| 970 | #define TPACPI_HOTKEY_MAP_TYPESIZE sizeof(ibm_keycode_map[0]) | ||
| 971 | |||
| 972 | int res, i; | ||
| 973 | int status; | ||
| 814 | 974 | ||
| 815 | vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n"); | 975 | vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n"); |
| 816 | 976 | ||
| 977 | BUG_ON(!tpacpi_inputdev); | ||
| 978 | |||
| 817 | IBM_ACPIHANDLE_INIT(hkey); | 979 | IBM_ACPIHANDLE_INIT(hkey); |
| 818 | mutex_init(&hotkey_mutex); | 980 | mutex_init(&hotkey_mutex); |
| 819 | 981 | ||
| @@ -824,7 +986,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
| 824 | str_supported(tp_features.hotkey)); | 986 | str_supported(tp_features.hotkey)); |
| 825 | 987 | ||
| 826 | if (tp_features.hotkey) { | 988 | if (tp_features.hotkey) { |
| 827 | hotkey_dev_attributes = create_attr_set(4, NULL); | 989 | hotkey_dev_attributes = create_attr_set(7, NULL); |
| 828 | if (!hotkey_dev_attributes) | 990 | if (!hotkey_dev_attributes) |
| 829 | return -ENOMEM; | 991 | return -ENOMEM; |
| 830 | res = add_to_attr_set(hotkey_dev_attributes, | 992 | res = add_to_attr_set(hotkey_dev_attributes, |
| @@ -840,19 +1002,92 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) | |||
| 840 | vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n", | 1002 | vdbg_printk(TPACPI_DBG_INIT, "hotkey masks are %s\n", |
| 841 | str_supported(tp_features.hotkey_mask)); | 1003 | str_supported(tp_features.hotkey_mask)); |
| 842 | 1004 | ||
| 1005 | if (tp_features.hotkey_mask) { | ||
| 1006 | /* MHKA available in A31, R40, R40e, T4x, X31, and later */ | ||
| 1007 | if (!acpi_evalf(hkey_handle, &hotkey_all_mask, | ||
| 1008 | "MHKA", "qd")) | ||
| 1009 | hotkey_all_mask = 0x080cU; /* FN+F12, FN+F4, FN+F3 */ | ||
| 1010 | } | ||
| 1011 | |||
| 843 | res = hotkey_get(&hotkey_orig_status, &hotkey_orig_mask); | 1012 | res = hotkey_get(&hotkey_orig_status, &hotkey_orig_mask); |
| 844 | if (!res && tp_features.hotkey_mask) { | 1013 | if (!res && tp_features.hotkey_mask) { |
| 845 | res = add_many_to_attr_set(hotkey_dev_attributes, | 1014 | res = add_many_to_attr_set(hotkey_dev_attributes, |
| 846 | hotkey_mask_attributes, | 1015 | hotkey_mask_attributes, |
| 847 | ARRAY_SIZE(hotkey_mask_attributes)); | 1016 | ARRAY_SIZE(hotkey_mask_attributes)); |
| 848 | } | 1017 | } |
| 1018 | |||
| 1019 | /* Not all thinkpads have a hardware radio switch */ | ||
| 1020 | if (!res && acpi_evalf(hkey_handle, &status, "WLSW", "qd")) { | ||
| 1021 | tp_features.hotkey_wlsw = 1; | ||
| 1022 | printk(IBM_INFO | ||
| 1023 | "radio switch found; radios are %s\n", | ||
| 1024 | enabled(status, 0)); | ||
| 1025 | res = add_to_attr_set(hotkey_dev_attributes, | ||
| 1026 | &dev_attr_hotkey_radio_sw.attr); | ||
| 1027 | } | ||
| 1028 | |||
| 849 | if (!res) | 1029 | if (!res) |
| 850 | res = register_attr_set_with_sysfs( | 1030 | res = register_attr_set_with_sysfs( |
| 851 | hotkey_dev_attributes, | 1031 | hotkey_dev_attributes, |
| 852 | &tpacpi_pdev->dev.kobj); | 1032 | &tpacpi_pdev->dev.kobj); |
| 1033 | if (res) | ||
| 1034 | return res; | ||
| 1035 | |||
| 1036 | /* Set up key map */ | ||
| 1037 | |||
| 1038 | hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE, | ||
| 1039 | GFP_KERNEL); | ||
| 1040 | if (!hotkey_keycode_map) { | ||
| 1041 | printk(IBM_ERR "failed to allocate memory for key map\n"); | ||
| 1042 | return -ENOMEM; | ||
| 1043 | } | ||
| 1044 | |||
| 1045 | if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) { | ||
| 1046 | dbg_printk(TPACPI_DBG_INIT, | ||
| 1047 | "using Lenovo default hot key map\n"); | ||
| 1048 | memcpy(hotkey_keycode_map, &lenovo_keycode_map, | ||
| 1049 | TPACPI_HOTKEY_MAP_SIZE); | ||
| 1050 | } else { | ||
| 1051 | dbg_printk(TPACPI_DBG_INIT, | ||
| 1052 | "using IBM default hot key map\n"); | ||
| 1053 | memcpy(hotkey_keycode_map, &ibm_keycode_map, | ||
| 1054 | TPACPI_HOTKEY_MAP_SIZE); | ||
| 1055 | } | ||
| 853 | 1056 | ||
| 1057 | #ifndef CONFIG_THINKPAD_ACPI_INPUT_ENABLED | ||
| 1058 | for (i = 0; i < 12; i++) | ||
| 1059 | hotkey_keycode_map[i] = KEY_UNKNOWN; | ||
| 1060 | #endif /* ! CONFIG_THINKPAD_ACPI_INPUT_ENABLED */ | ||
| 1061 | |||
| 1062 | set_bit(EV_KEY, tpacpi_inputdev->evbit); | ||
| 1063 | set_bit(EV_MSC, tpacpi_inputdev->evbit); | ||
| 1064 | set_bit(MSC_SCAN, tpacpi_inputdev->mscbit); | ||
| 1065 | tpacpi_inputdev->keycodesize = TPACPI_HOTKEY_MAP_TYPESIZE; | ||
| 1066 | tpacpi_inputdev->keycodemax = TPACPI_HOTKEY_MAP_LEN; | ||
| 1067 | tpacpi_inputdev->keycode = hotkey_keycode_map; | ||
| 1068 | for (i = 0; i < TPACPI_HOTKEY_MAP_LEN; i++) { | ||
| 1069 | if (hotkey_keycode_map[i] != KEY_RESERVED) { | ||
| 1070 | set_bit(hotkey_keycode_map[i], | ||
| 1071 | tpacpi_inputdev->keybit); | ||
| 1072 | } else { | ||
| 1073 | if (i < sizeof(hotkey_reserved_mask)*8) | ||
| 1074 | hotkey_reserved_mask |= 1 << i; | ||
| 1075 | } | ||
| 1076 | } | ||
| 1077 | |||
| 1078 | if (tp_features.hotkey_wlsw) { | ||
| 1079 | set_bit(EV_SW, tpacpi_inputdev->evbit); | ||
| 1080 | set_bit(SW_RADIO, tpacpi_inputdev->swbit); | ||
| 1081 | } | ||
| 1082 | |||
| 1083 | #ifdef CONFIG_THINKPAD_ACPI_INPUT_ENABLED | ||
| 1084 | dbg_printk(TPACPI_DBG_INIT, | ||
| 1085 | "enabling hot key handling\n"); | ||
| 1086 | res = hotkey_set(1, (hotkey_all_mask & ~hotkey_reserved_mask) | ||
| 1087 | | hotkey_orig_mask); | ||
| 854 | if (res) | 1088 | if (res) |
| 855 | return res; | 1089 | return res; |
| 1090 | #endif /* CONFIG_THINKPAD_ACPI_INPUT_ENABLED */ | ||
| 856 | } | 1091 | } |
| 857 | 1092 | ||
| 858 | return (tp_features.hotkey)? 0 : 1; | 1093 | return (tp_features.hotkey)? 0 : 1; |
| @@ -875,22 +1110,101 @@ static void hotkey_exit(void) | |||
| 875 | } | 1110 | } |
| 876 | } | 1111 | } |
| 877 | 1112 | ||
| 1113 | static void tpacpi_input_send_key(unsigned int scancode, | ||
| 1114 | unsigned int keycode) | ||
| 1115 | { | ||
| 1116 | if (keycode != KEY_RESERVED) { | ||
| 1117 | input_report_key(tpacpi_inputdev, keycode, 1); | ||
| 1118 | if (keycode == KEY_UNKNOWN) | ||
| 1119 | input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN, | ||
| 1120 | scancode); | ||
| 1121 | input_sync(tpacpi_inputdev); | ||
| 1122 | |||
| 1123 | input_report_key(tpacpi_inputdev, keycode, 0); | ||
| 1124 | if (keycode == KEY_UNKNOWN) | ||
| 1125 | input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN, | ||
| 1126 | scancode); | ||
| 1127 | input_sync(tpacpi_inputdev); | ||
| 1128 | } | ||
| 1129 | } | ||
| 1130 | |||
| 1131 | static void tpacpi_input_send_radiosw(void) | ||
| 1132 | { | ||
| 1133 | int wlsw; | ||
| 1134 | |||
| 1135 | if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw)) | ||
| 1136 | input_report_switch(tpacpi_inputdev, | ||
| 1137 | SW_RADIO, !!wlsw); | ||
| 1138 | } | ||
| 1139 | |||
| 878 | static void hotkey_notify(struct ibm_struct *ibm, u32 event) | 1140 | static void hotkey_notify(struct ibm_struct *ibm, u32 event) |
| 879 | { | 1141 | { |
| 880 | int hkey; | 1142 | u32 hkey; |
| 1143 | unsigned int keycode, scancode; | ||
| 1144 | int sendacpi = 1; | ||
| 1145 | |||
| 1146 | if (event == 0x80 && acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) { | ||
| 1147 | if (tpacpi_inputdev->users > 0) { | ||
| 1148 | switch (hkey >> 12) { | ||
| 1149 | case 1: | ||
| 1150 | /* 0x1000-0x1FFF: key presses */ | ||
| 1151 | scancode = hkey & 0xfff; | ||
| 1152 | if (scancode > 0 && scancode < 0x21) { | ||
| 1153 | scancode--; | ||
| 1154 | keycode = hotkey_keycode_map[scancode]; | ||
| 1155 | tpacpi_input_send_key(scancode, keycode); | ||
| 1156 | sendacpi = (keycode == KEY_RESERVED | ||
| 1157 | || keycode == KEY_UNKNOWN); | ||
| 1158 | } else { | ||
| 1159 | printk(IBM_ERR | ||
| 1160 | "hotkey 0x%04x out of range for keyboard map\n", | ||
| 1161 | hkey); | ||
| 1162 | } | ||
| 1163 | break; | ||
| 1164 | case 5: | ||
| 1165 | /* 0x5000-0x5FFF: LID */ | ||
| 1166 | /* we don't handle it through this path, just | ||
| 1167 | * eat up known LID events */ | ||
| 1168 | if (hkey != 0x5001 && hkey != 0x5002) { | ||
| 1169 | printk(IBM_ERR | ||
| 1170 | "unknown LID-related hotkey event: 0x%04x\n", | ||
| 1171 | hkey); | ||
| 1172 | } | ||
| 1173 | break; | ||
| 1174 | case 7: | ||
| 1175 | /* 0x7000-0x7FFF: misc */ | ||
| 1176 | if (tp_features.hotkey_wlsw && hkey == 0x7000) { | ||
| 1177 | tpacpi_input_send_radiosw(); | ||
| 1178 | sendacpi = 0; | ||
| 1179 | break; | ||
| 1180 | } | ||
| 1181 | /* fallthrough to default */ | ||
| 1182 | default: | ||
| 1183 | /* case 2: dock-related */ | ||
| 1184 | /* 0x2305 - T43 waking up due to bay lever eject while aslept */ | ||
| 1185 | /* case 3: ultra-bay related. maybe bay in dock? */ | ||
| 1186 | /* 0x3003 - T43 after wake up by bay lever eject (0x2305) */ | ||
| 1187 | printk(IBM_NOTICE "unhandled hotkey event 0x%04x\n", hkey); | ||
| 1188 | } | ||
| 1189 | } | ||
| 881 | 1190 | ||
| 882 | if (acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) | 1191 | if (sendacpi) |
| 883 | acpi_bus_generate_event(ibm->acpi->device, event, hkey); | 1192 | acpi_bus_generate_event(ibm->acpi->device, event, hkey); |
| 884 | else { | 1193 | } else { |
| 885 | printk(IBM_ERR "unknown hotkey event %d\n", event); | 1194 | printk(IBM_ERR "unknown hotkey notification event %d\n", event); |
| 886 | acpi_bus_generate_event(ibm->acpi->device, event, 0); | 1195 | acpi_bus_generate_event(ibm->acpi->device, event, 0); |
| 887 | } | 1196 | } |
| 888 | } | 1197 | } |
| 889 | 1198 | ||
| 1199 | static void hotkey_resume(void) | ||
| 1200 | { | ||
| 1201 | tpacpi_input_send_radiosw(); | ||
| 1202 | } | ||
| 1203 | |||
| 890 | /* | 1204 | /* |
| 891 | * Call with hotkey_mutex held | 1205 | * Call with hotkey_mutex held |
| 892 | */ | 1206 | */ |
| 893 | static int hotkey_get(int *status, int *mask) | 1207 | static int hotkey_get(int *status, u32 *mask) |
| 894 | { | 1208 | { |
| 895 | if (!acpi_evalf(hkey_handle, status, "DHKC", "d")) | 1209 | if (!acpi_evalf(hkey_handle, status, "DHKC", "d")) |
| 896 | return -EIO; | 1210 | return -EIO; |
| @@ -905,7 +1219,7 @@ static int hotkey_get(int *status, int *mask) | |||
| 905 | /* | 1219 | /* |
| 906 | * Call with hotkey_mutex held | 1220 | * Call with hotkey_mutex held |
| 907 | */ | 1221 | */ |
| 908 | static int hotkey_set(int status, int mask) | 1222 | static int hotkey_set(int status, u32 mask) |
| 909 | { | 1223 | { |
| 910 | int i; | 1224 | int i; |
| 911 | 1225 | ||
| @@ -926,7 +1240,8 @@ static int hotkey_set(int status, int mask) | |||
| 926 | /* procfs -------------------------------------------------------------- */ | 1240 | /* procfs -------------------------------------------------------------- */ |
| 927 | static int hotkey_read(char *p) | 1241 | static int hotkey_read(char *p) |
| 928 | { | 1242 | { |
| 929 | int res, status, mask; | 1243 | int res, status; |
| 1244 | u32 mask; | ||
| 930 | int len = 0; | 1245 | int len = 0; |
| 931 | 1246 | ||
| 932 | if (!tp_features.hotkey) { | 1247 | if (!tp_features.hotkey) { |
| @@ -944,7 +1259,7 @@ static int hotkey_read(char *p) | |||
| 944 | 1259 | ||
| 945 | len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0)); | 1260 | len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0)); |
| 946 | if (tp_features.hotkey_mask) { | 1261 | if (tp_features.hotkey_mask) { |
| 947 | len += sprintf(p + len, "mask:\t\t0x%04x\n", mask); | 1262 | len += sprintf(p + len, "mask:\t\t0x%08x\n", mask); |
| 948 | len += sprintf(p + len, | 1263 | len += sprintf(p + len, |
| 949 | "commands:\tenable, disable, reset, <mask>\n"); | 1264 | "commands:\tenable, disable, reset, <mask>\n"); |
| 950 | } else { | 1265 | } else { |
| @@ -957,7 +1272,8 @@ static int hotkey_read(char *p) | |||
| 957 | 1272 | ||
| 958 | static int hotkey_write(char *buf) | 1273 | static int hotkey_write(char *buf) |
| 959 | { | 1274 | { |
| 960 | int res, status, mask; | 1275 | int res, status; |
| 1276 | u32 mask; | ||
| 961 | char *cmd; | 1277 | char *cmd; |
| 962 | int do_cmd = 0; | 1278 | int do_cmd = 0; |
| 963 | 1279 | ||
| @@ -1012,6 +1328,7 @@ static struct ibm_struct hotkey_driver_data = { | |||
| 1012 | .read = hotkey_read, | 1328 | .read = hotkey_read, |
| 1013 | .write = hotkey_write, | 1329 | .write = hotkey_write, |
| 1014 | .exit = hotkey_exit, | 1330 | .exit = hotkey_exit, |
| 1331 | .resume = hotkey_resume, | ||
| 1015 | .acpi = &ibm_hotkey_acpidriver, | 1332 | .acpi = &ibm_hotkey_acpidriver, |
| 1016 | }; | 1333 | }; |
| 1017 | 1334 | ||
| @@ -1770,7 +2087,10 @@ static struct tp_acpi_drv_struct ibm_dock_acpidriver[2] = { | |||
| 1770 | .type = ACPI_SYSTEM_NOTIFY, | 2087 | .type = ACPI_SYSTEM_NOTIFY, |
| 1771 | }, | 2088 | }, |
| 1772 | { | 2089 | { |
| 1773 | .hid = IBM_PCI_HID, | 2090 | /* THIS ONE MUST NEVER BE USED FOR DRIVER AUTOLOADING. |
| 2091 | * We just use it to get notifications of dock hotplug | ||
| 2092 | * in very old thinkpads */ | ||
| 2093 | .hid = PCI_ROOT_HID_STRING, | ||
| 1774 | .notify = dock_notify, | 2094 | .notify = dock_notify, |
| 1775 | .handle = &pci_handle, | 2095 | .handle = &pci_handle, |
| 1776 | .type = ACPI_SYSTEM_NOTIFY, | 2096 | .type = ACPI_SYSTEM_NOTIFY, |
| @@ -1829,7 +2149,7 @@ static int __init dock_init2(struct ibm_init_struct *iibm) | |||
| 1829 | static void dock_notify(struct ibm_struct *ibm, u32 event) | 2149 | static void dock_notify(struct ibm_struct *ibm, u32 event) |
| 1830 | { | 2150 | { |
| 1831 | int docked = dock_docked(); | 2151 | int docked = dock_docked(); |
| 1832 | int pci = ibm->acpi->hid && strstr(ibm->acpi->hid, IBM_PCI_HID); | 2152 | int pci = ibm->acpi->hid && strstr(ibm->acpi->hid, PCI_ROOT_HID_STRING); |
| 1833 | 2153 | ||
| 1834 | if (event == 1 && !pci) /* 570 */ | 2154 | if (event == 1 && !pci) /* 570 */ |
| 1835 | acpi_bus_generate_event(ibm->acpi->device, event, 1); /* button */ | 2155 | acpi_bus_generate_event(ibm->acpi->device, event, 1); /* button */ |
| @@ -2389,7 +2709,7 @@ static int __init thermal_init(struct ibm_init_struct *iibm) | |||
| 2389 | 2709 | ||
| 2390 | acpi_tmp7 = acpi_evalf(ec_handle, NULL, "TMP7", "qv"); | 2710 | acpi_tmp7 = acpi_evalf(ec_handle, NULL, "TMP7", "qv"); |
| 2391 | 2711 | ||
| 2392 | if (ibm_thinkpad_ec_found && experimental) { | 2712 | if (thinkpad_id.ec_model) { |
| 2393 | /* | 2713 | /* |
| 2394 | * Direct EC access mode: sensors at registers | 2714 | * Direct EC access mode: sensors at registers |
| 2395 | * 0x78-0x7F, 0xC0-0xC7. Registers return 0x00 for | 2715 | * 0x78-0x7F, 0xC0-0xC7. Registers return 0x00 for |
| @@ -2533,6 +2853,8 @@ static int thermal_get_sensor(int idx, s32 *value) | |||
| 2533 | snprintf(tmpi, sizeof(tmpi), "TMP%c", '0' + idx); | 2853 | snprintf(tmpi, sizeof(tmpi), "TMP%c", '0' + idx); |
| 2534 | if (!acpi_evalf(ec_handle, &t, tmpi, "d")) | 2854 | if (!acpi_evalf(ec_handle, &t, tmpi, "d")) |
| 2535 | return -EIO; | 2855 | return -EIO; |
| 2856 | if (t > 127 || t < -127) | ||
| 2857 | t = TP_EC_THERMAL_TMP_NA; | ||
| 2536 | *value = t * 1000; | 2858 | *value = t * 1000; |
| 2537 | return 0; | 2859 | return 0; |
| 2538 | } | 2860 | } |
| @@ -2671,22 +2993,39 @@ static struct ibm_struct ecdump_driver_data = { | |||
| 2671 | * Backlight/brightness subdriver | 2993 | * Backlight/brightness subdriver |
| 2672 | */ | 2994 | */ |
| 2673 | 2995 | ||
| 2674 | static struct backlight_device *ibm_backlight_device = NULL; | 2996 | static struct backlight_device *ibm_backlight_device; |
| 2675 | 2997 | ||
| 2676 | static struct backlight_ops ibm_backlight_data = { | 2998 | static struct backlight_ops ibm_backlight_data = { |
| 2677 | .get_brightness = brightness_get, | 2999 | .get_brightness = brightness_get, |
| 2678 | .update_status = brightness_update_status, | 3000 | .update_status = brightness_update_status, |
| 2679 | }; | 3001 | }; |
| 2680 | 3002 | ||
| 3003 | static struct mutex brightness_mutex; | ||
| 3004 | |||
| 2681 | static int __init brightness_init(struct ibm_init_struct *iibm) | 3005 | static int __init brightness_init(struct ibm_init_struct *iibm) |
| 2682 | { | 3006 | { |
| 2683 | int b; | 3007 | int b; |
| 2684 | 3008 | ||
| 2685 | vdbg_printk(TPACPI_DBG_INIT, "initializing brightness subdriver\n"); | 3009 | vdbg_printk(TPACPI_DBG_INIT, "initializing brightness subdriver\n"); |
| 2686 | 3010 | ||
| 3011 | mutex_init(&brightness_mutex); | ||
| 3012 | |||
| 3013 | if (!brightness_mode) { | ||
| 3014 | if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) | ||
| 3015 | brightness_mode = 2; | ||
| 3016 | else | ||
| 3017 | brightness_mode = 3; | ||
| 3018 | |||
| 3019 | dbg_printk(TPACPI_DBG_INIT, "selected brightness_mode=%d\n", | ||
| 3020 | brightness_mode); | ||
| 3021 | } | ||
| 3022 | |||
| 3023 | if (brightness_mode > 3) | ||
| 3024 | return -EINVAL; | ||
| 3025 | |||
| 2687 | b = brightness_get(NULL); | 3026 | b = brightness_get(NULL); |
| 2688 | if (b < 0) | 3027 | if (b < 0) |
| 2689 | return b; | 3028 | return 1; |
| 2690 | 3029 | ||
| 2691 | ibm_backlight_device = backlight_device_register( | 3030 | ibm_backlight_device = backlight_device_register( |
| 2692 | TPACPI_BACKLIGHT_DEV_NAME, NULL, NULL, | 3031 | TPACPI_BACKLIGHT_DEV_NAME, NULL, NULL, |
| @@ -2722,34 +3061,79 @@ static int brightness_update_status(struct backlight_device *bd) | |||
| 2722 | bd->props.brightness : 0); | 3061 | bd->props.brightness : 0); |
| 2723 | } | 3062 | } |
| 2724 | 3063 | ||
| 3064 | /* | ||
| 3065 | * ThinkPads can read brightness from two places: EC 0x31, or | ||
| 3066 | * CMOS NVRAM byte 0x5E, bits 0-3. | ||
| 3067 | */ | ||
| 2725 | static int brightness_get(struct backlight_device *bd) | 3068 | static int brightness_get(struct backlight_device *bd) |
| 2726 | { | 3069 | { |
| 2727 | u8 level; | 3070 | u8 lec = 0, lcmos = 0, level = 0; |
| 2728 | if (!acpi_ec_read(brightness_offset, &level)) | ||
| 2729 | return -EIO; | ||
| 2730 | 3071 | ||
| 2731 | level &= 0x7; | 3072 | if (brightness_mode & 1) { |
| 3073 | if (!acpi_ec_read(brightness_offset, &lec)) | ||
| 3074 | return -EIO; | ||
| 3075 | lec &= 7; | ||
| 3076 | level = lec; | ||
| 3077 | }; | ||
| 3078 | if (brightness_mode & 2) { | ||
| 3079 | lcmos = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS) | ||
| 3080 | & TP_NVRAM_MASK_LEVEL_BRIGHTNESS) | ||
| 3081 | >> TP_NVRAM_POS_LEVEL_BRIGHTNESS; | ||
| 3082 | level = lcmos; | ||
| 3083 | } | ||
| 3084 | |||
| 3085 | if (brightness_mode == 3 && lec != lcmos) { | ||
| 3086 | printk(IBM_ERR | ||
| 3087 | "CMOS NVRAM (%u) and EC (%u) do not agree " | ||
| 3088 | "on display brightness level\n", | ||
| 3089 | (unsigned int) lcmos, | ||
| 3090 | (unsigned int) lec); | ||
| 3091 | return -EIO; | ||
| 3092 | } | ||
| 2732 | 3093 | ||
| 2733 | return level; | 3094 | return level; |
| 2734 | } | 3095 | } |
| 2735 | 3096 | ||
| 2736 | static int brightness_set(int value) | 3097 | static int brightness_set(int value) |
| 2737 | { | 3098 | { |
| 2738 | int cmos_cmd, inc, i; | 3099 | int cmos_cmd, inc, i, res; |
| 2739 | int current_value = brightness_get(NULL); | 3100 | int current_value; |
| 3101 | |||
| 3102 | if (value > 7) | ||
| 3103 | return -EINVAL; | ||
| 2740 | 3104 | ||
| 2741 | value &= 7; | 3105 | res = mutex_lock_interruptible(&brightness_mutex); |
| 3106 | if (res < 0) | ||
| 3107 | return res; | ||
| 3108 | |||
| 3109 | current_value = brightness_get(NULL); | ||
| 3110 | if (current_value < 0) { | ||
| 3111 | res = current_value; | ||
| 3112 | goto errout; | ||
| 3113 | } | ||
| 2742 | 3114 | ||
| 2743 | cmos_cmd = value > current_value ? TP_CMOS_BRIGHTNESS_UP : TP_CMOS_BRIGHTNESS_DOWN; | 3115 | cmos_cmd = value > current_value ? |
| 3116 | TP_CMOS_BRIGHTNESS_UP : | ||
| 3117 | TP_CMOS_BRIGHTNESS_DOWN; | ||
| 2744 | inc = value > current_value ? 1 : -1; | 3118 | inc = value > current_value ? 1 : -1; |
| 3119 | |||
| 3120 | res = 0; | ||
| 2745 | for (i = current_value; i != value; i += inc) { | 3121 | for (i = current_value; i != value; i += inc) { |
| 2746 | if (issue_thinkpad_cmos_command(cmos_cmd)) | 3122 | if ((brightness_mode & 2) && |
| 2747 | return -EIO; | 3123 | issue_thinkpad_cmos_command(cmos_cmd)) { |
| 2748 | if (!acpi_ec_write(brightness_offset, i + inc)) | 3124 | res = -EIO; |
| 2749 | return -EIO; | 3125 | goto errout; |
| 3126 | } | ||
| 3127 | if ((brightness_mode & 1) && | ||
| 3128 | !acpi_ec_write(brightness_offset, i + inc)) { | ||
| 3129 | res = -EIO; | ||
| 3130 | goto errout;; | ||
| 3131 | } | ||
| 2750 | } | 3132 | } |
| 2751 | 3133 | ||
| 2752 | return 0; | 3134 | errout: |
| 3135 | mutex_unlock(&brightness_mutex); | ||
| 3136 | return res; | ||
| 2753 | } | 3137 | } |
| 2754 | 3138 | ||
| 2755 | static int brightness_read(char *p) | 3139 | static int brightness_read(char *p) |
| @@ -3273,20 +3657,19 @@ static int __init fan_init(struct ibm_init_struct *iibm) | |||
| 3273 | * Enable for TP-1Y (T43), TP-78 (R51e), | 3657 | * Enable for TP-1Y (T43), TP-78 (R51e), |
| 3274 | * TP-76 (R52), TP-70 (T43, R52), which are known | 3658 | * TP-76 (R52), TP-70 (T43, R52), which are known |
| 3275 | * to be buggy. */ | 3659 | * to be buggy. */ |
| 3276 | if (fan_control_initial_status == 0x07 && | 3660 | if (fan_control_initial_status == 0x07) { |
| 3277 | ibm_thinkpad_ec_found && | 3661 | switch (thinkpad_id.ec_model) { |
| 3278 | ((ibm_thinkpad_ec_found[0] == '1' && | 3662 | case 0x5931: /* TP-1Y */ |
| 3279 | ibm_thinkpad_ec_found[1] == 'Y') || | 3663 | case 0x3837: /* TP-78 */ |
| 3280 | (ibm_thinkpad_ec_found[0] == '7' && | 3664 | case 0x3637: /* TP-76 */ |
| 3281 | (ibm_thinkpad_ec_found[1] == '6' || | 3665 | case 0x3037: /* TP-70 */ |
| 3282 | ibm_thinkpad_ec_found[1] == '8' || | 3666 | printk(IBM_NOTICE |
| 3283 | ibm_thinkpad_ec_found[1] == '0')) | 3667 | "fan_init: initial fan status is " |
| 3284 | )) { | 3668 | "unknown, assuming it is in auto " |
| 3285 | printk(IBM_NOTICE | 3669 | "mode\n"); |
| 3286 | "fan_init: initial fan status is " | 3670 | tp_features.fan_ctrl_status_undef = 1; |
| 3287 | "unknown, assuming it is in auto " | 3671 | ;; |
| 3288 | "mode\n"); | 3672 | } |
| 3289 | tp_features.fan_ctrl_status_undef = 1; | ||
| 3290 | } | 3673 | } |
| 3291 | } else { | 3674 | } else { |
| 3292 | printk(IBM_ERR | 3675 | printk(IBM_ERR |
| @@ -3474,7 +3857,7 @@ static void fan_watchdog_fire(struct work_struct *ignored) | |||
| 3474 | 3857 | ||
| 3475 | static void fan_watchdog_reset(void) | 3858 | static void fan_watchdog_reset(void) |
| 3476 | { | 3859 | { |
| 3477 | static int fan_watchdog_active = 0; | 3860 | static int fan_watchdog_active; |
| 3478 | 3861 | ||
| 3479 | if (fan_control_access_mode == TPACPI_FAN_WR_NONE) | 3862 | if (fan_control_access_mode == TPACPI_FAN_WR_NONE) |
| 3480 | return; | 3863 | return; |
| @@ -3877,7 +4260,7 @@ static struct ibm_struct fan_driver_data = { | |||
| 3877 | ****************************************************************************/ | 4260 | ****************************************************************************/ |
| 3878 | 4261 | ||
| 3879 | /* /proc support */ | 4262 | /* /proc support */ |
| 3880 | static struct proc_dir_entry *proc_dir = NULL; | 4263 | static struct proc_dir_entry *proc_dir; |
| 3881 | 4264 | ||
| 3882 | /* Subdriver registry */ | 4265 | /* Subdriver registry */ |
| 3883 | static LIST_HEAD(tpacpi_all_drivers); | 4266 | static LIST_HEAD(tpacpi_all_drivers); |
| @@ -4020,13 +4403,30 @@ static void ibm_exit(struct ibm_struct *ibm) | |||
| 4020 | 4403 | ||
| 4021 | /* Probing */ | 4404 | /* Probing */ |
| 4022 | 4405 | ||
| 4023 | static char *ibm_thinkpad_ec_found = NULL; | 4406 | static void __init get_thinkpad_model_data(struct thinkpad_id_data *tp) |
| 4024 | |||
| 4025 | static char* __init check_dmi_for_ec(void) | ||
| 4026 | { | 4407 | { |
| 4027 | struct dmi_device *dev = NULL; | 4408 | struct dmi_device *dev = NULL; |
| 4028 | char ec_fw_string[18]; | 4409 | char ec_fw_string[18]; |
| 4029 | 4410 | ||
| 4411 | if (!tp) | ||
| 4412 | return; | ||
| 4413 | |||
| 4414 | memset(tp, 0, sizeof(*tp)); | ||
| 4415 | |||
| 4416 | if (dmi_name_in_vendors("IBM")) | ||
| 4417 | tp->vendor = PCI_VENDOR_ID_IBM; | ||
| 4418 | else if (dmi_name_in_vendors("LENOVO")) | ||
| 4419 | tp->vendor = PCI_VENDOR_ID_LENOVO; | ||
| 4420 | else | ||
| 4421 | return; | ||
| 4422 | |||
| 4423 | tp->bios_version_str = kstrdup(dmi_get_system_info(DMI_BIOS_VERSION), | ||
| 4424 | GFP_KERNEL); | ||
| 4425 | if (!tp->bios_version_str) | ||
| 4426 | return; | ||
| 4427 | tp->bios_model = tp->bios_version_str[0] | ||
| 4428 | | (tp->bios_version_str[1] << 8); | ||
| 4429 | |||
| 4030 | /* | 4430 | /* |
| 4031 | * ThinkPad T23 or newer, A31 or newer, R50e or newer, | 4431 | * ThinkPad T23 or newer, A31 or newer, R50e or newer, |
| 4032 | * X32 or newer, all Z series; Some models must have an | 4432 | * X32 or newer, all Z series; Some models must have an |
| @@ -4040,10 +4440,20 @@ static char* __init check_dmi_for_ec(void) | |||
| 4040 | ec_fw_string) == 1) { | 4440 | ec_fw_string) == 1) { |
| 4041 | ec_fw_string[sizeof(ec_fw_string) - 1] = 0; | 4441 | ec_fw_string[sizeof(ec_fw_string) - 1] = 0; |
| 4042 | ec_fw_string[strcspn(ec_fw_string, " ]")] = 0; | 4442 | ec_fw_string[strcspn(ec_fw_string, " ]")] = 0; |
| 4043 | return kstrdup(ec_fw_string, GFP_KERNEL); | 4443 | |
| 4444 | tp->ec_version_str = kstrdup(ec_fw_string, GFP_KERNEL); | ||
| 4445 | tp->ec_model = ec_fw_string[0] | ||
| 4446 | | (ec_fw_string[1] << 8); | ||
| 4447 | break; | ||
| 4044 | } | 4448 | } |
| 4045 | } | 4449 | } |
| 4046 | return NULL; | 4450 | |
| 4451 | tp->model_str = kstrdup(dmi_get_system_info(DMI_PRODUCT_VERSION), | ||
| 4452 | GFP_KERNEL); | ||
| 4453 | if (strnicmp(tp->model_str, "ThinkPad", 8) != 0) { | ||
| 4454 | kfree(tp->model_str); | ||
| 4455 | tp->model_str = NULL; | ||
| 4456 | } | ||
| 4047 | } | 4457 | } |
| 4048 | 4458 | ||
| 4049 | static int __init probe_for_thinkpad(void) | 4459 | static int __init probe_for_thinkpad(void) |
| @@ -4057,7 +4467,7 @@ static int __init probe_for_thinkpad(void) | |||
| 4057 | * Non-ancient models have better DMI tagging, but very old models | 4467 | * Non-ancient models have better DMI tagging, but very old models |
| 4058 | * don't. | 4468 | * don't. |
| 4059 | */ | 4469 | */ |
| 4060 | is_thinkpad = dmi_name_in_vendors("ThinkPad"); | 4470 | is_thinkpad = (thinkpad_id.model_str != NULL); |
| 4061 | 4471 | ||
| 4062 | /* ec is required because many other handles are relative to it */ | 4472 | /* ec is required because many other handles are relative to it */ |
| 4063 | IBM_ACPIHANDLE_INIT(ec); | 4473 | IBM_ACPIHANDLE_INIT(ec); |
| @@ -4073,7 +4483,7 @@ static int __init probe_for_thinkpad(void) | |||
| 4073 | * false positives a damn great deal | 4483 | * false positives a damn great deal |
| 4074 | */ | 4484 | */ |
| 4075 | if (!is_thinkpad) | 4485 | if (!is_thinkpad) |
| 4076 | is_thinkpad = dmi_name_in_vendors("IBM"); | 4486 | is_thinkpad = (thinkpad_id.vendor == PCI_VENDOR_ID_IBM); |
| 4077 | 4487 | ||
| 4078 | if (!is_thinkpad && !force_load) | 4488 | if (!is_thinkpad && !force_load) |
| 4079 | return -ENODEV; | 4489 | return -ENODEV; |
| @@ -4185,10 +4595,13 @@ static u32 dbg_level; | |||
| 4185 | module_param_named(debug, dbg_level, uint, 0); | 4595 | module_param_named(debug, dbg_level, uint, 0); |
| 4186 | 4596 | ||
| 4187 | static int force_load; | 4597 | static int force_load; |
| 4188 | module_param(force_load, int, 0); | 4598 | module_param(force_load, bool, 0); |
| 4189 | 4599 | ||
| 4190 | static int fan_control_allowed; | 4600 | static int fan_control_allowed; |
| 4191 | module_param_named(fan_control, fan_control_allowed, int, 0); | 4601 | module_param_named(fan_control, fan_control_allowed, bool, 0); |
| 4602 | |||
| 4603 | static int brightness_mode; | ||
| 4604 | module_param_named(brightness_mode, brightness_mode, int, 0); | ||
| 4192 | 4605 | ||
| 4193 | #define IBM_PARAM(feature) \ | 4606 | #define IBM_PARAM(feature) \ |
| 4194 | module_param_call(feature, set_ibm_param, NULL, NULL, 0) | 4607 | module_param_call(feature, set_ibm_param, NULL, NULL, 0) |
| @@ -4216,12 +4629,16 @@ static int __init thinkpad_acpi_module_init(void) | |||
| 4216 | int ret, i; | 4629 | int ret, i; |
| 4217 | 4630 | ||
| 4218 | /* Driver-level probe */ | 4631 | /* Driver-level probe */ |
| 4632 | |||
| 4633 | get_thinkpad_model_data(&thinkpad_id); | ||
| 4219 | ret = probe_for_thinkpad(); | 4634 | ret = probe_for_thinkpad(); |
| 4220 | if (ret) | 4635 | if (ret) { |
| 4636 | thinkpad_acpi_module_exit(); | ||
| 4221 | return ret; | 4637 | return ret; |
| 4638 | } | ||
| 4222 | 4639 | ||
| 4223 | /* Driver initialization */ | 4640 | /* Driver initialization */ |
| 4224 | ibm_thinkpad_ec_found = check_dmi_for_ec(); | 4641 | |
| 4225 | IBM_ACPIHANDLE_INIT(ecrd); | 4642 | IBM_ACPIHANDLE_INIT(ecrd); |
| 4226 | IBM_ACPIHANDLE_INIT(ecwr); | 4643 | IBM_ACPIHANDLE_INIT(ecwr); |
| 4227 | 4644 | ||
| @@ -4265,6 +4682,22 @@ static int __init thinkpad_acpi_module_init(void) | |||
| 4265 | thinkpad_acpi_module_exit(); | 4682 | thinkpad_acpi_module_exit(); |
| 4266 | return ret; | 4683 | return ret; |
| 4267 | } | 4684 | } |
| 4685 | tpacpi_inputdev = input_allocate_device(); | ||
| 4686 | if (!tpacpi_inputdev) { | ||
| 4687 | printk(IBM_ERR "unable to allocate input device\n"); | ||
| 4688 | thinkpad_acpi_module_exit(); | ||
| 4689 | return -ENOMEM; | ||
| 4690 | } else { | ||
| 4691 | /* Prepare input device, but don't register */ | ||
| 4692 | tpacpi_inputdev->name = "ThinkPad Extra Buttons"; | ||
| 4693 | tpacpi_inputdev->phys = IBM_DRVR_NAME "/input0"; | ||
| 4694 | tpacpi_inputdev->id.bustype = BUS_HOST; | ||
| 4695 | tpacpi_inputdev->id.vendor = (thinkpad_id.vendor) ? | ||
| 4696 | thinkpad_id.vendor : | ||
| 4697 | PCI_VENDOR_ID_IBM; | ||
| 4698 | tpacpi_inputdev->id.product = TPACPI_HKEY_INPUT_PRODUCT; | ||
| 4699 | tpacpi_inputdev->id.version = TPACPI_HKEY_INPUT_VERSION; | ||
| 4700 | } | ||
| 4268 | for (i = 0; i < ARRAY_SIZE(ibms_init); i++) { | 4701 | for (i = 0; i < ARRAY_SIZE(ibms_init); i++) { |
| 4269 | ret = ibm_init(&ibms_init[i]); | 4702 | ret = ibm_init(&ibms_init[i]); |
| 4270 | if (ret >= 0 && *ibms_init[i].param) | 4703 | if (ret >= 0 && *ibms_init[i].param) |
| @@ -4274,6 +4707,14 @@ static int __init thinkpad_acpi_module_init(void) | |||
| 4274 | return ret; | 4707 | return ret; |
| 4275 | } | 4708 | } |
| 4276 | } | 4709 | } |
| 4710 | ret = input_register_device(tpacpi_inputdev); | ||
| 4711 | if (ret < 0) { | ||
| 4712 | printk(IBM_ERR "unable to register input device\n"); | ||
| 4713 | thinkpad_acpi_module_exit(); | ||
| 4714 | return ret; | ||
| 4715 | } else { | ||
| 4716 | tp_features.input_device_registered = 1; | ||
| 4717 | } | ||
| 4277 | 4718 | ||
| 4278 | return 0; | 4719 | return 0; |
| 4279 | } | 4720 | } |
| @@ -4290,6 +4731,13 @@ static void thinkpad_acpi_module_exit(void) | |||
| 4290 | 4731 | ||
| 4291 | dbg_printk(TPACPI_DBG_INIT, "finished subdriver exit path...\n"); | 4732 | dbg_printk(TPACPI_DBG_INIT, "finished subdriver exit path...\n"); |
| 4292 | 4733 | ||
| 4734 | if (tpacpi_inputdev) { | ||
| 4735 | if (tp_features.input_device_registered) | ||
| 4736 | input_unregister_device(tpacpi_inputdev); | ||
| 4737 | else | ||
| 4738 | input_free_device(tpacpi_inputdev); | ||
| 4739 | } | ||
| 4740 | |||
| 4293 | if (tpacpi_hwmon) | 4741 | if (tpacpi_hwmon) |
| 4294 | hwmon_device_unregister(tpacpi_hwmon); | 4742 | hwmon_device_unregister(tpacpi_hwmon); |
| 4295 | 4743 | ||
| @@ -4302,7 +4750,9 @@ static void thinkpad_acpi_module_exit(void) | |||
| 4302 | if (proc_dir) | 4750 | if (proc_dir) |
| 4303 | remove_proc_entry(IBM_PROC_DIR, acpi_root_dir); | 4751 | remove_proc_entry(IBM_PROC_DIR, acpi_root_dir); |
| 4304 | 4752 | ||
| 4305 | kfree(ibm_thinkpad_ec_found); | 4753 | kfree(thinkpad_id.bios_version_str); |
| 4754 | kfree(thinkpad_id.ec_version_str); | ||
| 4755 | kfree(thinkpad_id.model_str); | ||
| 4306 | } | 4756 | } |
| 4307 | 4757 | ||
| 4308 | module_init(thinkpad_acpi_module_init); | 4758 | module_init(thinkpad_acpi_module_init); |
diff --git a/drivers/misc/thinkpad_acpi.h b/drivers/misc/thinkpad_acpi.h index 72d62f2dabb9..b7a4a888cc8b 100644 --- a/drivers/misc/thinkpad_acpi.h +++ b/drivers/misc/thinkpad_acpi.h | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/list.h> | 32 | #include <linux/list.h> |
| 33 | #include <linux/mutex.h> | 33 | #include <linux/mutex.h> |
| 34 | 34 | ||
| 35 | #include <linux/nvram.h> | ||
| 35 | #include <linux/proc_fs.h> | 36 | #include <linux/proc_fs.h> |
| 36 | #include <linux/sysfs.h> | 37 | #include <linux/sysfs.h> |
| 37 | #include <linux/backlight.h> | 38 | #include <linux/backlight.h> |
| @@ -39,6 +40,7 @@ | |||
| 39 | #include <linux/platform_device.h> | 40 | #include <linux/platform_device.h> |
| 40 | #include <linux/hwmon.h> | 41 | #include <linux/hwmon.h> |
| 41 | #include <linux/hwmon-sysfs.h> | 42 | #include <linux/hwmon-sysfs.h> |
| 43 | #include <linux/input.h> | ||
| 42 | #include <asm/uaccess.h> | 44 | #include <asm/uaccess.h> |
| 43 | 45 | ||
| 44 | #include <linux/dmi.h> | 46 | #include <linux/dmi.h> |
| @@ -48,6 +50,7 @@ | |||
| 48 | #include <acpi/acpi_drivers.h> | 50 | #include <acpi/acpi_drivers.h> |
| 49 | #include <acpi/acnamesp.h> | 51 | #include <acpi/acnamesp.h> |
| 50 | 52 | ||
| 53 | #include <linux/pci_ids.h> | ||
| 51 | 54 | ||
| 52 | /**************************************************************************** | 55 | /**************************************************************************** |
| 53 | * Main driver | 56 | * Main driver |
| @@ -78,6 +81,11 @@ | |||
| 78 | #define TP_CMOS_BRIGHTNESS_UP 4 | 81 | #define TP_CMOS_BRIGHTNESS_UP 4 |
| 79 | #define TP_CMOS_BRIGHTNESS_DOWN 5 | 82 | #define TP_CMOS_BRIGHTNESS_DOWN 5 |
| 80 | 83 | ||
| 84 | /* ThinkPad CMOS NVRAM constants */ | ||
| 85 | #define TP_NVRAM_ADDR_BRIGHTNESS 0x5e | ||
| 86 | #define TP_NVRAM_MASK_LEVEL_BRIGHTNESS 0x07 | ||
| 87 | #define TP_NVRAM_POS_LEVEL_BRIGHTNESS 0 | ||
| 88 | |||
| 81 | #define onoff(status,bit) ((status) & (1 << (bit)) ? "on" : "off") | 89 | #define onoff(status,bit) ((status) & (1 << (bit)) ? "on" : "off") |
| 82 | #define enabled(status,bit) ((status) & (1 << (bit)) ? "enabled" : "disabled") | 90 | #define enabled(status,bit) ((status) & (1 << (bit)) ? "enabled" : "disabled") |
| 83 | #define strlencmp(a,b) (strncmp((a), (b), strlen(b))) | 91 | #define strlencmp(a,b) (strncmp((a), (b), strlen(b))) |
| @@ -98,9 +106,13 @@ static const char *str_supported(int is_supported); | |||
| 98 | #define vdbg_printk(a_dbg_level, format, arg...) | 106 | #define vdbg_printk(a_dbg_level, format, arg...) |
| 99 | #endif | 107 | #endif |
| 100 | 108 | ||
| 109 | /* Input IDs */ | ||
| 110 | #define TPACPI_HKEY_INPUT_VENDOR PCI_VENDOR_ID_IBM | ||
| 111 | #define TPACPI_HKEY_INPUT_PRODUCT 0x5054 /* "TP" */ | ||
| 112 | #define TPACPI_HKEY_INPUT_VERSION 0x4101 | ||
| 113 | |||
| 101 | /* ACPI HIDs */ | 114 | /* ACPI HIDs */ |
| 102 | #define IBM_HKEY_HID "IBM0068" | 115 | #define IBM_HKEY_HID "IBM0068" |
| 103 | #define IBM_PCI_HID "PNP0A03" | ||
| 104 | 116 | ||
| 105 | /* ACPI helpers */ | 117 | /* ACPI helpers */ |
| 106 | static int __must_check acpi_evalf(acpi_handle handle, | 118 | static int __must_check acpi_evalf(acpi_handle handle, |
| @@ -161,6 +173,7 @@ static int parse_strtoul(const char *buf, unsigned long max, | |||
| 161 | static struct platform_device *tpacpi_pdev; | 173 | static struct platform_device *tpacpi_pdev; |
| 162 | static struct class_device *tpacpi_hwmon; | 174 | static struct class_device *tpacpi_hwmon; |
| 163 | static struct platform_driver tpacpi_pdriver; | 175 | static struct platform_driver tpacpi_pdriver; |
| 176 | static struct input_dev *tpacpi_inputdev; | ||
| 164 | static int tpacpi_create_driver_attributes(struct device_driver *drv); | 177 | static int tpacpi_create_driver_attributes(struct device_driver *drv); |
| 165 | static void tpacpi_remove_driver_attributes(struct device_driver *drv); | 178 | static void tpacpi_remove_driver_attributes(struct device_driver *drv); |
| 166 | 179 | ||
| @@ -168,9 +181,7 @@ static void tpacpi_remove_driver_attributes(struct device_driver *drv); | |||
| 168 | static int experimental; | 181 | static int experimental; |
| 169 | static u32 dbg_level; | 182 | static u32 dbg_level; |
| 170 | static int force_load; | 183 | static int force_load; |
| 171 | static char *ibm_thinkpad_ec_found; | ||
| 172 | 184 | ||
| 173 | static char* check_dmi_for_ec(void); | ||
| 174 | static int thinkpad_acpi_module_init(void); | 185 | static int thinkpad_acpi_module_init(void); |
| 175 | static void thinkpad_acpi_module_exit(void); | 186 | static void thinkpad_acpi_module_exit(void); |
| 176 | 187 | ||
| @@ -197,6 +208,7 @@ struct ibm_struct { | |||
| 197 | int (*read) (char *); | 208 | int (*read) (char *); |
| 198 | int (*write) (char *); | 209 | int (*write) (char *); |
| 199 | void (*exit) (void); | 210 | void (*exit) (void); |
| 211 | void (*resume) (void); | ||
| 200 | 212 | ||
| 201 | struct list_head all_drivers; | 213 | struct list_head all_drivers; |
| 202 | 214 | ||
| @@ -228,12 +240,29 @@ static struct { | |||
| 228 | u16 bluetooth:1; | 240 | u16 bluetooth:1; |
| 229 | u16 hotkey:1; | 241 | u16 hotkey:1; |
| 230 | u16 hotkey_mask:1; | 242 | u16 hotkey_mask:1; |
| 243 | u16 hotkey_wlsw:1; | ||
| 231 | u16 light:1; | 244 | u16 light:1; |
| 232 | u16 light_status:1; | 245 | u16 light_status:1; |
| 233 | u16 wan:1; | 246 | u16 wan:1; |
| 234 | u16 fan_ctrl_status_undef:1; | 247 | u16 fan_ctrl_status_undef:1; |
| 248 | u16 input_device_registered:1; | ||
| 235 | } tp_features; | 249 | } tp_features; |
| 236 | 250 | ||
| 251 | struct thinkpad_id_data { | ||
| 252 | unsigned int vendor; /* ThinkPad vendor: | ||
| 253 | * PCI_VENDOR_ID_IBM/PCI_VENDOR_ID_LENOVO */ | ||
| 254 | |||
| 255 | char *bios_version_str; /* Something like 1ZET51WW (1.03z) */ | ||
| 256 | char *ec_version_str; /* Something like 1ZHT51WW-1.04a */ | ||
| 257 | |||
| 258 | u16 bios_model; /* Big Endian, TP-1Y = 0x5931, 0 = unknown */ | ||
| 259 | u16 ec_model; | ||
| 260 | |||
| 261 | char *model_str; | ||
| 262 | }; | ||
| 263 | |||
| 264 | static struct thinkpad_id_data thinkpad_id; | ||
| 265 | |||
| 237 | static struct list_head tpacpi_all_drivers; | 266 | static struct list_head tpacpi_all_drivers; |
| 238 | 267 | ||
| 239 | static struct ibm_init_struct ibms_init[]; | 268 | static struct ibm_init_struct ibms_init[]; |
| @@ -300,6 +329,7 @@ static int bluetooth_write(char *buf); | |||
| 300 | 329 | ||
| 301 | static struct backlight_device *ibm_backlight_device; | 330 | static struct backlight_device *ibm_backlight_device; |
| 302 | static int brightness_offset = 0x31; | 331 | static int brightness_offset = 0x31; |
| 332 | static int brightness_mode; | ||
| 303 | 333 | ||
| 304 | static int brightness_init(struct ibm_init_struct *iibm); | 334 | static int brightness_init(struct ibm_init_struct *iibm); |
| 305 | static void brightness_exit(void); | 335 | static void brightness_exit(void); |
| @@ -415,14 +445,14 @@ static int fan_write_cmd_watchdog(const char *cmd, int *rc); | |||
| 415 | */ | 445 | */ |
| 416 | 446 | ||
| 417 | static int hotkey_orig_status; | 447 | static int hotkey_orig_status; |
| 418 | static int hotkey_orig_mask; | 448 | static u32 hotkey_orig_mask; |
| 419 | 449 | ||
| 420 | static struct mutex hotkey_mutex; | 450 | static struct mutex hotkey_mutex; |
| 421 | 451 | ||
| 422 | static int hotkey_init(struct ibm_init_struct *iibm); | 452 | static int hotkey_init(struct ibm_init_struct *iibm); |
| 423 | static void hotkey_exit(void); | 453 | static void hotkey_exit(void); |
| 424 | static int hotkey_get(int *status, int *mask); | 454 | static int hotkey_get(int *status, u32 *mask); |
| 425 | static int hotkey_set(int status, int mask); | 455 | static int hotkey_set(int status, u32 mask); |
| 426 | static void hotkey_notify(struct ibm_struct *ibm, u32 event); | 456 | static void hotkey_notify(struct ibm_struct *ibm, u32 event); |
| 427 | static int hotkey_read(char *p); | 457 | static int hotkey_read(char *p); |
| 428 | static int hotkey_write(char *buf); | 458 | static int hotkey_write(char *buf); |
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c index 3c45142c40b2..b01985498460 100644 --- a/drivers/pcmcia/m8xx_pcmcia.c +++ b/drivers/pcmcia/m8xx_pcmcia.c | |||
| @@ -1316,7 +1316,7 @@ static struct of_device_id m8xx_pcmcia_match[] = { | |||
| 1316 | MODULE_DEVICE_TABLE(of, m8xx_pcmcia_match); | 1316 | MODULE_DEVICE_TABLE(of, m8xx_pcmcia_match); |
| 1317 | 1317 | ||
| 1318 | static struct of_platform_driver m8xx_pcmcia_driver = { | 1318 | static struct of_platform_driver m8xx_pcmcia_driver = { |
| 1319 | .name = (char *)driver_name, | 1319 | .name = driver_name, |
| 1320 | .match_table = m8xx_pcmcia_match, | 1320 | .match_table = m8xx_pcmcia_match, |
| 1321 | .probe = m8xx_probe, | 1321 | .probe = m8xx_probe, |
| 1322 | .remove = m8xx_remove, | 1322 | .remove = m8xx_remove, |
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 2a237f09ee5d..564cc9b51822 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
| @@ -12,6 +12,13 @@ config VGASTATE | |||
| 12 | tristate | 12 | tristate |
| 13 | default n | 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 | config FB | 22 | config FB |
| 16 | tristate "Support for frame buffer devices" | 23 | tristate "Support for frame buffer devices" |
| 17 | ---help--- | 24 | ---help--- |
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index a562f9d69d2c..518933d4905f 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
| @@ -123,3 +123,6 @@ obj-$(CONFIG_FB_OF) += offb.o | |||
| 123 | 123 | ||
| 124 | # the test framebuffer is last | 124 | # the test framebuffer is last |
| 125 | obj-$(CONFIG_FB_VIRTUAL) += vfb.o | 125 | obj-$(CONFIG_FB_VIRTUAL) += vfb.o |
| 126 | |||
| 127 | #video output switch sysfs driver | ||
| 128 | obj-$(CONFIG_VIDEO_OUTPUT_CONTROL) += output.o | ||
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index b34b7a711d5b..b2a851c1b8cb 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
| @@ -732,7 +732,7 @@ static int nfs_parse_mount_options(char *raw, | |||
| 732 | return 0; | 732 | return 0; |
| 733 | if (option < 0 || option > 65535) | 733 | if (option < 0 || option > 65535) |
| 734 | return 0; | 734 | return 0; |
| 735 | mnt->nfs_server.address.sin_port = htonl(option); | 735 | mnt->nfs_server.address.sin_port = htons(option); |
| 736 | break; | 736 | break; |
| 737 | case Opt_rsize: | 737 | case Opt_rsize: |
| 738 | if (match_int(args, &mnt->rsize)) | 738 | if (match_int(args, &mnt->rsize)) |
diff --git a/include/acpi/acmacros.h b/include/acpi/acmacros.h index 8948a6461834..45662f6dbdb6 100644 --- a/include/acpi/acmacros.h +++ b/include/acpi/acmacros.h | |||
| @@ -486,6 +486,8 @@ | |||
| 486 | #define ACPI_FUNCTION_NAME(name) | 486 | #define ACPI_FUNCTION_NAME(name) |
| 487 | #endif | 487 | #endif |
| 488 | 488 | ||
| 489 | #ifdef DEBUG_FUNC_TRACE | ||
| 490 | |||
| 489 | #define ACPI_FUNCTION_TRACE(a) ACPI_FUNCTION_NAME(a) \ | 491 | #define ACPI_FUNCTION_TRACE(a) ACPI_FUNCTION_NAME(a) \ |
| 490 | acpi_ut_trace(ACPI_DEBUG_PARAMETERS) | 492 | acpi_ut_trace(ACPI_DEBUG_PARAMETERS) |
| 491 | #define ACPI_FUNCTION_TRACE_PTR(a,b) ACPI_FUNCTION_NAME(a) \ | 493 | #define ACPI_FUNCTION_TRACE_PTR(a,b) ACPI_FUNCTION_NAME(a) \ |
| @@ -563,6 +565,27 @@ | |||
| 563 | 565 | ||
| 564 | #endif /* ACPI_SIMPLE_RETURN_MACROS */ | 566 | #endif /* ACPI_SIMPLE_RETURN_MACROS */ |
| 565 | 567 | ||
| 568 | #else /* !DEBUG_FUNC_TRACE */ | ||
| 569 | |||
| 570 | #define ACPI_FUNCTION_TRACE(a) | ||
| 571 | #define ACPI_FUNCTION_TRACE_PTR(a,b) | ||
| 572 | #define ACPI_FUNCTION_TRACE_U32(a,b) | ||
| 573 | #define ACPI_FUNCTION_TRACE_STR(a,b) | ||
| 574 | #define ACPI_FUNCTION_EXIT | ||
| 575 | #define ACPI_FUNCTION_STATUS_EXIT(s) | ||
| 576 | #define ACPI_FUNCTION_VALUE_EXIT(s) | ||
| 577 | #define ACPI_FUNCTION_TRACE(a) | ||
| 578 | #define ACPI_FUNCTION_ENTRY() | ||
| 579 | |||
| 580 | #define return_VOID return | ||
| 581 | #define return_ACPI_STATUS(s) return(s) | ||
| 582 | #define return_VALUE(s) return(s) | ||
| 583 | #define return_UINT8(s) return(s) | ||
| 584 | #define return_UINT32(s) return(s) | ||
| 585 | #define return_PTR(s) return(s) | ||
| 586 | |||
| 587 | #endif /* DEBUG_FUNC_TRACE */ | ||
| 588 | |||
| 566 | /* Conditional execution */ | 589 | /* Conditional execution */ |
| 567 | 590 | ||
| 568 | #define ACPI_DEBUG_EXEC(a) a | 591 | #define ACPI_DEBUG_EXEC(a) a |
| @@ -599,26 +622,26 @@ | |||
| 599 | #define ACPI_DEBUG_EXEC(a) | 622 | #define ACPI_DEBUG_EXEC(a) |
| 600 | #define ACPI_NORMAL_EXEC(a) a; | 623 | #define ACPI_NORMAL_EXEC(a) a; |
| 601 | 624 | ||
| 602 | #define ACPI_DEBUG_DEFINE(a) | 625 | #define ACPI_DEBUG_DEFINE(a) do { } while(0) |
| 603 | #define ACPI_DEBUG_ONLY_MEMBERS(a) | 626 | #define ACPI_DEBUG_ONLY_MEMBERS(a) do { } while(0) |
| 604 | #define ACPI_FUNCTION_NAME(a) | 627 | #define ACPI_FUNCTION_NAME(a) do { } while(0) |
| 605 | #define ACPI_FUNCTION_TRACE(a) | 628 | #define ACPI_FUNCTION_TRACE(a) do { } while(0) |
| 606 | #define ACPI_FUNCTION_TRACE_PTR(a,b) | 629 | #define ACPI_FUNCTION_TRACE_PTR(a,b) do { } while(0) |
| 607 | #define ACPI_FUNCTION_TRACE_U32(a,b) | 630 | #define ACPI_FUNCTION_TRACE_U32(a,b) do { } while(0) |
| 608 | #define ACPI_FUNCTION_TRACE_STR(a,b) | 631 | #define ACPI_FUNCTION_TRACE_STR(a,b) do { } while(0) |
| 609 | #define ACPI_FUNCTION_EXIT | 632 | #define ACPI_FUNCTION_EXIT do { } while(0) |
| 610 | #define ACPI_FUNCTION_STATUS_EXIT(s) | 633 | #define ACPI_FUNCTION_STATUS_EXIT(s) do { } while(0) |
| 611 | #define ACPI_FUNCTION_VALUE_EXIT(s) | 634 | #define ACPI_FUNCTION_VALUE_EXIT(s) do { } while(0) |
| 612 | #define ACPI_FUNCTION_ENTRY() | 635 | #define ACPI_FUNCTION_ENTRY() do { } while(0) |
| 613 | #define ACPI_DUMP_STACK_ENTRY(a) | 636 | #define ACPI_DUMP_STACK_ENTRY(a) do { } while(0) |
| 614 | #define ACPI_DUMP_OPERANDS(a,b,c,d,e) | 637 | #define ACPI_DUMP_OPERANDS(a,b,c,d,e) do { } while(0) |
| 615 | #define ACPI_DUMP_ENTRY(a,b) | 638 | #define ACPI_DUMP_ENTRY(a,b) do { } while(0) |
| 616 | #define ACPI_DUMP_TABLES(a,b) | 639 | #define ACPI_DUMP_TABLES(a,b) do { } while(0) |
| 617 | #define ACPI_DUMP_PATHNAME(a,b,c,d) | 640 | #define ACPI_DUMP_PATHNAME(a,b,c,d) do { } while(0) |
| 618 | #define ACPI_DUMP_RESOURCE_LIST(a) | 641 | #define ACPI_DUMP_RESOURCE_LIST(a) do { } while(0) |
| 619 | #define ACPI_DUMP_BUFFER(a,b) | 642 | #define ACPI_DUMP_BUFFER(a,b) do { } while(0) |
| 620 | #define ACPI_DEBUG_PRINT(pl) | 643 | #define ACPI_DEBUG_PRINT(pl) do { } while(0) |
| 621 | #define ACPI_DEBUG_PRINT_RAW(pl) | 644 | #define ACPI_DEBUG_PRINT_RAW(pl) do { } while(0) |
| 622 | 645 | ||
| 623 | #define return_VOID return | 646 | #define return_VOID return |
| 624 | #define return_ACPI_STATUS(s) return(s) | 647 | #define return_ACPI_STATUS(s) return(s) |
diff --git a/include/acpi/acoutput.h b/include/acpi/acoutput.h index 7812267b577f..c090a8b0bc99 100644 --- a/include/acpi/acoutput.h +++ b/include/acpi/acoutput.h | |||
| @@ -178,8 +178,8 @@ | |||
| 178 | 178 | ||
| 179 | /* Defaults for debug_level, debug and normal */ | 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) | 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 | ACPI_LV_DEBUG_OBJECT) | 182 | #define ACPI_NORMAL_DEFAULT (ACPI_LV_INIT | ACPI_LV_WARN | ACPI_LV_ERROR) |
| 183 | #define ACPI_DEBUG_ALL (ACPI_LV_AML_DISASSEMBLE | ACPI_LV_ALL_EXCEPTIONS | ACPI_LV_ALL) | 183 | #define ACPI_DEBUG_ALL (ACPI_LV_AML_DISASSEMBLE | ACPI_LV_ALL_EXCEPTIONS | ACPI_LV_ALL) |
| 184 | 184 | ||
| 185 | #endif /* __ACOUTPUT_H__ */ | 185 | #endif /* __ACOUTPUT_H__ */ |
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index c6fa5e023bc7..5e3dcf3299bf 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
| @@ -321,7 +321,8 @@ struct acpi_bus_event { | |||
| 321 | }; | 321 | }; |
| 322 | 322 | ||
| 323 | extern struct kset acpi_subsys; | 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 | * External Functions | 327 | * External Functions |
| 327 | */ | 328 | */ |
diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h index dab2ec59a3b0..c785485e62a6 100644 --- a/include/acpi/platform/acenv.h +++ b/include/acpi/platform/acenv.h | |||
| @@ -136,7 +136,7 @@ | |||
| 136 | 136 | ||
| 137 | /*! [Begin] no source code translation */ | 137 | /*! [Begin] no source code translation */ |
| 138 | 138 | ||
| 139 | #if defined(__linux__) | 139 | #if defined(_LINUX) || defined(__linux__) |
| 140 | #include "aclinux.h" | 140 | #include "aclinux.h" |
| 141 | 141 | ||
| 142 | #elif defined(_AED_EFI) | 142 | #elif defined(_AED_EFI) |
diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h index a568717f98c6..6ed15a0978eb 100644 --- a/include/acpi/platform/aclinux.h +++ b/include/acpi/platform/aclinux.h | |||
| @@ -91,7 +91,10 @@ | |||
| 91 | #define ACPI_USE_NATIVE_DIVIDE | 91 | #define ACPI_USE_NATIVE_DIVIDE |
| 92 | #endif | 92 | #endif |
| 93 | 93 | ||
| 94 | #ifndef __cdecl | ||
| 94 | #define __cdecl | 95 | #define __cdecl |
| 96 | #endif | ||
| 97 | |||
| 95 | #define ACPI_FLUSH_CPU_CACHE() | 98 | #define ACPI_FLUSH_CPU_CACHE() |
| 96 | #endif /* __KERNEL__ */ | 99 | #endif /* __KERNEL__ */ |
| 97 | 100 | ||
diff --git a/include/acpi/processor.h b/include/acpi/processor.h index b4b0ffdab098..f9f987f8e661 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h | |||
| @@ -21,6 +21,8 @@ | |||
| 21 | #define ACPI_PSD_REV0_REVISION 0 /* Support for _PSD as in ACPI 3.0 */ | 21 | #define ACPI_PSD_REV0_REVISION 0 /* Support for _PSD as in ACPI 3.0 */ |
| 22 | #define ACPI_PSD_REV0_ENTRIES 5 | 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 | * Types of coordination defined in ACPI 3.0. Same macros can be used across | 27 | * Types of coordination defined in ACPI 3.0. Same macros can be used across |
| 26 | * P, C and T states | 28 | * P, C and T states |
| @@ -125,17 +127,53 @@ struct acpi_processor_performance { | |||
| 125 | 127 | ||
| 126 | /* Throttling Control */ | 128 | /* Throttling Control */ |
| 127 | 129 | ||
| 130 | struct acpi_tsd_package { | ||
| 131 | acpi_integer num_entries; | ||
| 132 | acpi_integer revision; | ||
| 133 | acpi_integer domain; | ||
| 134 | acpi_integer coord_type; | ||
| 135 | acpi_integer num_processors; | ||
| 136 | } __attribute__ ((packed)); | ||
| 137 | |||
| 138 | struct acpi_ptc_register { | ||
| 139 | u8 descriptor; | ||
| 140 | u16 length; | ||
| 141 | u8 space_id; | ||
| 142 | u8 bit_width; | ||
| 143 | u8 bit_offset; | ||
| 144 | u8 reserved; | ||
| 145 | u64 address; | ||
| 146 | } __attribute__ ((packed)); | ||
| 147 | |||
| 148 | struct acpi_processor_tx_tss { | ||
| 149 | acpi_integer freqpercentage; /* */ | ||
| 150 | acpi_integer power; /* milliWatts */ | ||
| 151 | acpi_integer transition_latency; /* microseconds */ | ||
| 152 | acpi_integer control; /* control value */ | ||
| 153 | acpi_integer status; /* success indicator */ | ||
| 154 | }; | ||
| 128 | struct acpi_processor_tx { | 155 | struct acpi_processor_tx { |
| 129 | u16 power; | 156 | u16 power; |
| 130 | u16 performance; | 157 | u16 performance; |
| 131 | }; | 158 | }; |
| 132 | 159 | ||
| 160 | struct acpi_processor; | ||
| 133 | struct acpi_processor_throttling { | 161 | struct acpi_processor_throttling { |
| 134 | int state; | 162 | unsigned int state; |
| 163 | unsigned int platform_limit; | ||
| 164 | struct acpi_pct_register control_register; | ||
| 165 | struct acpi_pct_register status_register; | ||
| 166 | unsigned int state_count; | ||
| 167 | struct acpi_processor_tx_tss *states_tss; | ||
| 168 | struct acpi_tsd_package domain_info; | ||
| 169 | cpumask_t shared_cpu_map; | ||
| 170 | int (*acpi_processor_get_throttling) (struct acpi_processor * pr); | ||
| 171 | int (*acpi_processor_set_throttling) (struct acpi_processor * pr, | ||
| 172 | int state); | ||
| 173 | |||
| 135 | u32 address; | 174 | u32 address; |
| 136 | u8 duty_offset; | 175 | u8 duty_offset; |
| 137 | u8 duty_width; | 176 | u8 duty_width; |
| 138 | int state_count; | ||
| 139 | struct acpi_processor_tx states[ACPI_PROCESSOR_MAX_THROTTLING]; | 177 | struct acpi_processor_tx states[ACPI_PROCESSOR_MAX_THROTTLING]; |
| 140 | }; | 178 | }; |
| 141 | 179 | ||
| @@ -169,6 +207,9 @@ struct acpi_processor { | |||
| 169 | u32 id; | 207 | u32 id; |
| 170 | u32 pblk; | 208 | u32 pblk; |
| 171 | int performance_platform_limit; | 209 | int performance_platform_limit; |
| 210 | int throttling_platform_limit; | ||
| 211 | /* 0 - states 0..n-th state available */ | ||
| 212 | |||
| 172 | struct acpi_processor_flags flags; | 213 | struct acpi_processor_flags flags; |
| 173 | struct acpi_processor_power power; | 214 | struct acpi_processor_power power; |
| 174 | struct acpi_processor_performance *performance; | 215 | struct acpi_processor_performance *performance; |
| @@ -270,7 +311,7 @@ static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr) | |||
| 270 | 311 | ||
| 271 | /* in processor_throttling.c */ | 312 | /* in processor_throttling.c */ |
| 272 | int acpi_processor_get_throttling_info(struct acpi_processor *pr); | 313 | int acpi_processor_get_throttling_info(struct acpi_processor *pr); |
| 273 | int acpi_processor_set_throttling(struct acpi_processor *pr, int state); | 314 | extern int acpi_processor_set_throttling(struct acpi_processor *pr, int state); |
| 274 | extern struct file_operations acpi_processor_throttling_fops; | 315 | extern struct file_operations acpi_processor_throttling_fops; |
| 275 | 316 | ||
| 276 | /* in processor_idle.c */ | 317 | /* in processor_idle.c */ |
diff --git a/include/asm-i386/alternative.h b/include/asm-i386/alternative.h index eb7da5402bfa..bda6c810c0f4 100644 --- a/include/asm-i386/alternative.h +++ b/include/asm-i386/alternative.h | |||
| @@ -149,4 +149,6 @@ apply_paravirt(struct paravirt_patch_site *start, | |||
| 149 | #define __parainstructions_end NULL | 149 | #define __parainstructions_end NULL |
| 150 | #endif | 150 | #endif |
| 151 | 151 | ||
| 152 | extern void text_poke(void *addr, unsigned char *opcode, int len); | ||
| 153 | |||
| 152 | #endif /* _I386_ALTERNATIVE_H */ | 154 | #endif /* _I386_ALTERNATIVE_H */ |
diff --git a/include/asm-i386/cmpxchg.h b/include/asm-i386/cmpxchg.h index 64dcdf46117b..f86ede28f6dc 100644 --- a/include/asm-i386/cmpxchg.h +++ b/include/asm-i386/cmpxchg.h | |||
| @@ -34,7 +34,7 @@ static inline void __set_64bit (unsigned long long * ptr, | |||
| 34 | "\n1:\t" | 34 | "\n1:\t" |
| 35 | "movl (%0), %%eax\n\t" | 35 | "movl (%0), %%eax\n\t" |
| 36 | "movl 4(%0), %%edx\n\t" | 36 | "movl 4(%0), %%edx\n\t" |
| 37 | "lock cmpxchg8b (%0)\n\t" | 37 | LOCK_PREFIX "cmpxchg8b (%0)\n\t" |
| 38 | "jnz 1b" | 38 | "jnz 1b" |
| 39 | : /* no outputs */ | 39 | : /* no outputs */ |
| 40 | : "D"(ptr), | 40 | : "D"(ptr), |
diff --git a/include/asm-i386/mce.h b/include/asm-i386/mce.h index b0a02ee34ffd..d56d89742e8f 100644 --- a/include/asm-i386/mce.h +++ b/include/asm-i386/mce.h | |||
| @@ -5,3 +5,7 @@ extern void mcheck_init(struct cpuinfo_x86 *c); | |||
| 5 | #endif | 5 | #endif |
| 6 | 6 | ||
| 7 | extern int mce_disabled; | 7 | extern int mce_disabled; |
| 8 | |||
| 9 | extern void stop_mce(void); | ||
| 10 | extern void restart_mce(void); | ||
| 11 | |||
diff --git a/include/asm-i386/nmi.h b/include/asm-i386/nmi.h index fb1e133efd9f..ff30c98f87b0 100644 --- a/include/asm-i386/nmi.h +++ b/include/asm-i386/nmi.h | |||
| @@ -57,5 +57,7 @@ unsigned lapic_adjust_nmi_hz(unsigned hz); | |||
| 57 | int lapic_watchdog_ok(void); | 57 | int lapic_watchdog_ok(void); |
| 58 | void disable_lapic_nmi_watchdog(void); | 58 | void disable_lapic_nmi_watchdog(void); |
| 59 | void enable_lapic_nmi_watchdog(void); | 59 | void enable_lapic_nmi_watchdog(void); |
| 60 | void stop_nmi(void); | ||
| 61 | void restart_nmi(void); | ||
| 60 | 62 | ||
| 61 | #endif /* ASM_NMI_H */ | 63 | #endif /* ASM_NMI_H */ |
diff --git a/include/asm-i386/processor-cyrix.h b/include/asm-i386/processor-cyrix.h new file mode 100644 index 000000000000..97568ada1f97 --- /dev/null +++ b/include/asm-i386/processor-cyrix.h | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | /* | ||
| 2 | * NSC/Cyrix CPU indexed register access. Must be inlined instead of | ||
| 3 | * macros to ensure correct access ordering | ||
| 4 | * Access order is always 0x22 (=offset), 0x23 (=value) | ||
| 5 | * | ||
| 6 | * When using the old macros a line like | ||
| 7 | * setCx86(CX86_CCR2, getCx86(CX86_CCR2) | 0x88); | ||
| 8 | * gets expanded to: | ||
| 9 | * do { | ||
| 10 | * outb((CX86_CCR2), 0x22); | ||
| 11 | * outb((({ | ||
| 12 | * outb((CX86_CCR2), 0x22); | ||
| 13 | * inb(0x23); | ||
| 14 | * }) | 0x88), 0x23); | ||
| 15 | * } while (0); | ||
| 16 | * | ||
| 17 | * which in fact violates the access order (= 0x22, 0x22, 0x23, 0x23). | ||
| 18 | */ | ||
| 19 | |||
| 20 | static inline u8 getCx86(u8 reg) | ||
| 21 | { | ||
| 22 | outb(reg, 0x22); | ||
| 23 | return inb(0x23); | ||
| 24 | } | ||
| 25 | |||
| 26 | static inline void setCx86(u8 reg, u8 data) | ||
| 27 | { | ||
| 28 | outb(reg, 0x22); | ||
| 29 | outb(data, 0x23); | ||
| 30 | } | ||
diff --git a/include/asm-i386/processor.h b/include/asm-i386/processor.h index 48a7f69bb767..3845fe72383e 100644 --- a/include/asm-i386/processor.h +++ b/include/asm-i386/processor.h | |||
| @@ -168,17 +168,6 @@ static inline void clear_in_cr4 (unsigned long mask) | |||
| 168 | write_cr4(cr4); | 168 | write_cr4(cr4); |
| 169 | } | 169 | } |
| 170 | 170 | ||
| 171 | /* | ||
| 172 | * NSC/Cyrix CPU indexed register access macros | ||
| 173 | */ | ||
| 174 | |||
| 175 | #define getCx86(reg) ({ outb((reg), 0x22); inb(0x23); }) | ||
| 176 | |||
| 177 | #define setCx86(reg, data) do { \ | ||
| 178 | outb((reg), 0x22); \ | ||
| 179 | outb((data), 0x23); \ | ||
| 180 | } while (0) | ||
| 181 | |||
| 182 | /* Stop speculative execution */ | 171 | /* Stop speculative execution */ |
| 183 | static inline void sync_core(void) | 172 | static inline void sync_core(void) |
| 184 | { | 173 | { |
diff --git a/include/asm-powerpc/mpic.h b/include/asm-powerpc/mpic.h index 2ffb06abe881..262db6b8da73 100644 --- a/include/asm-powerpc/mpic.h +++ b/include/asm-powerpc/mpic.h | |||
| @@ -296,6 +296,9 @@ struct mpic | |||
| 296 | unsigned int dcr_base; | 296 | unsigned int dcr_base; |
| 297 | #endif | 297 | #endif |
| 298 | 298 | ||
| 299 | /* Protected sources */ | ||
| 300 | unsigned long *protected; | ||
| 301 | |||
| 299 | #ifdef CONFIG_MPIC_WEIRD | 302 | #ifdef CONFIG_MPIC_WEIRD |
| 300 | /* Pointer to HW info array */ | 303 | /* Pointer to HW info array */ |
| 301 | u32 *hw_set; | 304 | u32 *hw_set; |
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index 6e391c9894ce..672083787a1d 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h | |||
| @@ -139,7 +139,7 @@ extern unsigned long __init of_get_flat_dt_root(void); | |||
| 139 | 139 | ||
| 140 | /* For updating the device tree at runtime */ | 140 | /* For updating the device tree at runtime */ |
| 141 | extern void of_attach_node(struct device_node *); | 141 | extern void of_attach_node(struct device_node *); |
| 142 | extern void of_detach_node(const struct device_node *); | 142 | extern void of_detach_node(struct device_node *); |
| 143 | 143 | ||
| 144 | /* Other Prototypes */ | 144 | /* Other Prototypes */ |
| 145 | extern void finish_device_tree(void); | 145 | extern void finish_device_tree(void); |
diff --git a/include/asm-ppc/system.h b/include/asm-ppc/system.h index f1311a8f310f..cc45780421ca 100644 --- a/include/asm-ppc/system.h +++ b/include/asm-ppc/system.h | |||
| @@ -54,6 +54,7 @@ extern void show_regs(struct pt_regs * regs); | |||
| 54 | extern void flush_instruction_cache(void); | 54 | extern void flush_instruction_cache(void); |
| 55 | extern void hard_reset_now(void); | 55 | extern void hard_reset_now(void); |
| 56 | extern void poweroff_now(void); | 56 | extern void poweroff_now(void); |
| 57 | extern int set_dabr(unsigned long dabr); | ||
| 57 | #ifdef CONFIG_6xx | 58 | #ifdef CONFIG_6xx |
| 58 | extern long _get_L2CR(void); | 59 | extern long _get_L2CR(void); |
| 59 | extern long _get_L3CR(void); | 60 | extern long _get_L3CR(void); |
diff --git a/include/asm-x86_64/alternative.h b/include/asm-x86_64/alternative.h index eea7aecfac78..ab161e810151 100644 --- a/include/asm-x86_64/alternative.h +++ b/include/asm-x86_64/alternative.h | |||
| @@ -154,4 +154,6 @@ apply_paravirt(struct paravirt_patch *start, struct paravirt_patch *end) | |||
| 154 | #define __parainstructions_end NULL | 154 | #define __parainstructions_end NULL |
| 155 | #endif | 155 | #endif |
| 156 | 156 | ||
| 157 | extern void text_poke(void *addr, unsigned char *opcode, int len); | ||
| 158 | |||
| 157 | #endif /* _X86_64_ALTERNATIVE_H */ | 159 | #endif /* _X86_64_ALTERNATIVE_H */ |
diff --git a/include/asm-x86_64/cmpxchg.h b/include/asm-x86_64/cmpxchg.h index 09a6b6b6b74d..5e182062e6ec 100644 --- a/include/asm-x86_64/cmpxchg.h +++ b/include/asm-x86_64/cmpxchg.h | |||
| @@ -128,7 +128,7 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr, | |||
| 128 | ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\ | 128 | ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\ |
| 129 | (unsigned long)(n),sizeof(*(ptr)))) | 129 | (unsigned long)(n),sizeof(*(ptr)))) |
| 130 | #define cmpxchg_local(ptr,o,n)\ | 130 | #define cmpxchg_local(ptr,o,n)\ |
| 131 | ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\ | 131 | ((__typeof__(*(ptr)))__cmpxchg_local((ptr),(unsigned long)(o),\ |
| 132 | (unsigned long)(n),sizeof(*(ptr)))) | 132 | (unsigned long)(n),sizeof(*(ptr)))) |
| 133 | 133 | ||
| 134 | #endif | 134 | #endif |
diff --git a/include/asm-x86_64/hypertransport.h b/include/asm-x86_64/hypertransport.h index c16c6ff4bdd7..5cbf9fa5e0b5 100644 --- a/include/asm-x86_64/hypertransport.h +++ b/include/asm-x86_64/hypertransport.h | |||
| @@ -1,42 +1 @@ | |||
| 1 | #ifndef ASM_HYPERTRANSPORT_H | #include <asm-i386/hypertransport.h> | |
| 2 | #define ASM_HYPERTRANSPORT_H | ||
| 3 | |||
| 4 | /* | ||
| 5 | * Constants for x86 Hypertransport Interrupts. | ||
| 6 | */ | ||
| 7 | |||
| 8 | #define HT_IRQ_LOW_BASE 0xf8000000 | ||
| 9 | |||
| 10 | #define HT_IRQ_LOW_VECTOR_SHIFT 16 | ||
| 11 | #define HT_IRQ_LOW_VECTOR_MASK 0x00ff0000 | ||
| 12 | #define HT_IRQ_LOW_VECTOR(v) (((v) << HT_IRQ_LOW_VECTOR_SHIFT) & HT_IRQ_LOW_VECTOR_MASK) | ||
| 13 | |||
| 14 | #define HT_IRQ_LOW_DEST_ID_SHIFT 8 | ||
| 15 | #define HT_IRQ_LOW_DEST_ID_MASK 0x0000ff00 | ||
| 16 | #define HT_IRQ_LOW_DEST_ID(v) (((v) << HT_IRQ_LOW_DEST_ID_SHIFT) & HT_IRQ_LOW_DEST_ID_MASK) | ||
| 17 | |||
| 18 | #define HT_IRQ_LOW_DM_PHYSICAL 0x0000000 | ||
| 19 | #define HT_IRQ_LOW_DM_LOGICAL 0x0000040 | ||
| 20 | |||
| 21 | #define HT_IRQ_LOW_RQEOI_EDGE 0x0000000 | ||
| 22 | #define HT_IRQ_LOW_RQEOI_LEVEL 0x0000020 | ||
| 23 | |||
| 24 | |||
| 25 | #define HT_IRQ_LOW_MT_FIXED 0x0000000 | ||
| 26 | #define HT_IRQ_LOW_MT_ARBITRATED 0x0000004 | ||
| 27 | #define HT_IRQ_LOW_MT_SMI 0x0000008 | ||
| 28 | #define HT_IRQ_LOW_MT_NMI 0x000000c | ||
| 29 | #define HT_IRQ_LOW_MT_INIT 0x0000010 | ||
| 30 | #define HT_IRQ_LOW_MT_STARTUP 0x0000014 | ||
| 31 | #define HT_IRQ_LOW_MT_EXTINT 0x0000018 | ||
| 32 | #define HT_IRQ_LOW_MT_LINT1 0x000008c | ||
| 33 | #define HT_IRQ_LOW_MT_LINT0 0x0000098 | ||
| 34 | |||
| 35 | #define HT_IRQ_LOW_IRQ_MASKED 0x0000001 | ||
| 36 | |||
| 37 | |||
| 38 | #define HT_IRQ_HIGH_DEST_ID_SHIFT 0 | ||
| 39 | #define HT_IRQ_HIGH_DEST_ID_MASK 0x00ffffff | ||
| 40 | #define HT_IRQ_HIGH_DEST_ID(v) ((((v) >> 8) << HT_IRQ_HIGH_DEST_ID_SHIFT) & HT_IRQ_HIGH_DEST_ID_MASK) | ||
| 41 | |||
| 42 | #endif /* ASM_HYPERTRANSPORT_H */ | ||
diff --git a/include/asm-x86_64/mce.h b/include/asm-x86_64/mce.h index 556be5563e30..7bc030a1996d 100644 --- a/include/asm-x86_64/mce.h +++ b/include/asm-x86_64/mce.h | |||
| @@ -107,6 +107,9 @@ extern void do_machine_check(struct pt_regs *, long); | |||
| 107 | 107 | ||
| 108 | extern int mce_notify_user(void); | 108 | extern int mce_notify_user(void); |
| 109 | 109 | ||
| 110 | extern void stop_mce(void); | ||
| 111 | extern void restart_mce(void); | ||
| 112 | |||
| 110 | #endif | 113 | #endif |
| 111 | 114 | ||
| 112 | #endif | 115 | #endif |
diff --git a/include/asm-x86_64/msidef.h b/include/asm-x86_64/msidef.h index 5b8acddb70fb..083ad5827e48 100644 --- a/include/asm-x86_64/msidef.h +++ b/include/asm-x86_64/msidef.h | |||
| @@ -1,47 +1 @@ | |||
| 1 | #ifndef ASM_MSIDEF_H | #include <asm-i386/msidef.h> | |
| 2 | #define ASM_MSIDEF_H | ||
| 3 | |||
| 4 | /* | ||
| 5 | * Constants for Intel APIC based MSI messages. | ||
| 6 | */ | ||
| 7 | |||
| 8 | /* | ||
| 9 | * Shifts for MSI data | ||
| 10 | */ | ||
| 11 | |||
| 12 | #define MSI_DATA_VECTOR_SHIFT 0 | ||
| 13 | #define MSI_DATA_VECTOR_MASK 0x000000ff | ||
| 14 | #define MSI_DATA_VECTOR(v) (((v) << MSI_DATA_VECTOR_SHIFT) & MSI_DATA_VECTOR_MASK) | ||
| 15 | |||
| 16 | #define MSI_DATA_DELIVERY_MODE_SHIFT 8 | ||
| 17 | #define MSI_DATA_DELIVERY_FIXED (0 << MSI_DATA_DELIVERY_MODE_SHIFT) | ||
| 18 | #define MSI_DATA_DELIVERY_LOWPRI (1 << MSI_DATA_DELIVERY_MODE_SHIFT) | ||
| 19 | |||
| 20 | #define MSI_DATA_LEVEL_SHIFT 14 | ||
| 21 | #define MSI_DATA_LEVEL_DEASSERT (0 << MSI_DATA_LEVEL_SHIFT) | ||
| 22 | #define MSI_DATA_LEVEL_ASSERT (1 << MSI_DATA_LEVEL_SHIFT) | ||
| 23 | |||
| 24 | #define MSI_DATA_TRIGGER_SHIFT 15 | ||
| 25 | #define MSI_DATA_TRIGGER_EDGE (0 << MSI_DATA_TRIGGER_SHIFT) | ||
| 26 | #define MSI_DATA_TRIGGER_LEVEL (1 << MSI_DATA_TRIGGER_SHIFT) | ||
| 27 | |||
| 28 | /* | ||
| 29 | * Shift/mask fields for msi address | ||
| 30 | */ | ||
| 31 | |||
| 32 | #define MSI_ADDR_BASE_HI 0 | ||
| 33 | #define MSI_ADDR_BASE_LO 0xfee00000 | ||
| 34 | |||
| 35 | #define MSI_ADDR_DEST_MODE_SHIFT 2 | ||
| 36 | #define MSI_ADDR_DEST_MODE_PHYSICAL (0 << MSI_ADDR_DEST_MODE_SHIFT) | ||
| 37 | #define MSI_ADDR_DEST_MODE_LOGICAL (1 << MSI_ADDR_DEST_MODE_SHIFT) | ||
| 38 | |||
| 39 | #define MSI_ADDR_REDIRECTION_SHIFT 3 | ||
| 40 | #define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT) /* dedicated cpu */ | ||
| 41 | #define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT) /* lowest priority */ | ||
| 42 | |||
| 43 | #define MSI_ADDR_DEST_ID_SHIFT 12 | ||
| 44 | #define MSI_ADDR_DEST_ID_MASK 0x00ffff0 | ||
| 45 | #define MSI_ADDR_DEST_ID(dest) (((dest) << MSI_ADDR_DEST_ID_SHIFT) & MSI_ADDR_DEST_ID_MASK) | ||
| 46 | |||
| 47 | #endif /* ASM_MSIDEF_H */ | ||
diff --git a/include/asm-x86_64/nmi.h b/include/asm-x86_64/nmi.h index d0a7f53b1497..5fb3c0de5ccc 100644 --- a/include/asm-x86_64/nmi.h +++ b/include/asm-x86_64/nmi.h | |||
| @@ -88,5 +88,7 @@ unsigned lapic_adjust_nmi_hz(unsigned hz); | |||
| 88 | int lapic_watchdog_ok(void); | 88 | int lapic_watchdog_ok(void); |
| 89 | void disable_lapic_nmi_watchdog(void); | 89 | void disable_lapic_nmi_watchdog(void); |
| 90 | void enable_lapic_nmi_watchdog(void); | 90 | void enable_lapic_nmi_watchdog(void); |
| 91 | void stop_nmi(void); | ||
| 92 | void restart_nmi(void); | ||
| 91 | 93 | ||
| 92 | #endif /* ASM_NMI_H */ | 94 | #endif /* ASM_NMI_H */ |
diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h index 60cff1e4f7a3..c9d8764c89d1 100644 --- a/include/asm-x86_64/pgtable.h +++ b/include/asm-x86_64/pgtable.h | |||
| @@ -403,6 +403,8 @@ extern struct list_head pgd_list; | |||
| 403 | 403 | ||
| 404 | extern int kern_addr_valid(unsigned long addr); | 404 | extern int kern_addr_valid(unsigned long addr); |
| 405 | 405 | ||
| 406 | pte_t *lookup_address(unsigned long addr); | ||
| 407 | |||
| 406 | #define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ | 408 | #define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ |
| 407 | remap_pfn_range(vma, vaddr, pfn, size, prot) | 409 | remap_pfn_range(vma, vaddr, pfn, size, prot) |
| 408 | 410 | ||
diff --git a/include/asm-x86_64/processor.h b/include/asm-x86_64/processor.h index a1645bbc03bd..19525175b91c 100644 --- a/include/asm-x86_64/processor.h +++ b/include/asm-x86_64/processor.h | |||
| @@ -389,17 +389,6 @@ static inline void prefetchw(void *x) | |||
| 389 | 389 | ||
| 390 | #define cpu_relax() rep_nop() | 390 | #define cpu_relax() rep_nop() |
| 391 | 391 | ||
| 392 | /* | ||
| 393 | * NSC/Cyrix CPU indexed register access macros | ||
| 394 | */ | ||
| 395 | |||
| 396 | #define getCx86(reg) ({ outb((reg), 0x22); inb(0x23); }) | ||
| 397 | |||
| 398 | #define setCx86(reg, data) do { \ | ||
| 399 | outb((reg), 0x22); \ | ||
| 400 | outb((data), 0x23); \ | ||
| 401 | } while (0) | ||
| 402 | |||
| 403 | static inline void serialize_cpu(void) | 392 | static inline void serialize_cpu(void) |
| 404 | { | 393 | { |
| 405 | __asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx"); | 394 | __asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx"); |
diff --git a/include/asm-x86_64/proto.h b/include/asm-x86_64/proto.h index d6e3225549c0..31f20ad65876 100644 --- a/include/asm-x86_64/proto.h +++ b/include/asm-x86_64/proto.h | |||
| @@ -75,8 +75,6 @@ extern void setup_node_bootmem(int nodeid, unsigned long start, unsigned long en | |||
| 75 | extern void early_quirks(void); | 75 | extern void early_quirks(void); |
| 76 | extern void check_efer(void); | 76 | extern void check_efer(void); |
| 77 | 77 | ||
| 78 | extern int unhandled_signal(struct task_struct *tsk, int sig); | ||
| 79 | |||
| 80 | extern void select_idle_routine(const struct cpuinfo_x86 *c); | 78 | extern void select_idle_routine(const struct cpuinfo_x86 *c); |
| 81 | 79 | ||
| 82 | extern unsigned long table_start, table_end; | 80 | extern unsigned long table_start, table_end; |
diff --git a/include/asm-x86_64/system.h b/include/asm-x86_64/system.h index 6313d33a0686..02175aa1d16a 100644 --- a/include/asm-x86_64/system.h +++ b/include/asm-x86_64/system.h | |||
| @@ -75,19 +75,31 @@ static inline unsigned long read_cr0(void) | |||
| 75 | unsigned long cr0; | 75 | unsigned long cr0; |
| 76 | asm volatile("movq %%cr0,%0" : "=r" (cr0)); | 76 | asm volatile("movq %%cr0,%0" : "=r" (cr0)); |
| 77 | return cr0; | 77 | return cr0; |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | static inline void write_cr0(unsigned long val) | 80 | static inline void write_cr0(unsigned long val) |
| 81 | { | 81 | { |
| 82 | asm volatile("movq %0,%%cr0" :: "r" (val)); | 82 | asm volatile("movq %0,%%cr0" :: "r" (val)); |
| 83 | } | 83 | } |
| 84 | |||
| 85 | static inline unsigned long read_cr2(void) | ||
| 86 | { | ||
| 87 | unsigned long cr2; | ||
| 88 | asm("movq %%cr2,%0" : "=r" (cr2)); | ||
| 89 | return cr2; | ||
| 90 | } | ||
| 91 | |||
| 92 | static inline void write_cr2(unsigned long val) | ||
| 93 | { | ||
| 94 | asm volatile("movq %0,%%cr2" :: "r" (val)); | ||
| 95 | } | ||
| 84 | 96 | ||
| 85 | static inline unsigned long read_cr3(void) | 97 | static inline unsigned long read_cr3(void) |
| 86 | { | 98 | { |
| 87 | unsigned long cr3; | 99 | unsigned long cr3; |
| 88 | asm("movq %%cr3,%0" : "=r" (cr3)); | 100 | asm("movq %%cr3,%0" : "=r" (cr3)); |
| 89 | return cr3; | 101 | return cr3; |
| 90 | } | 102 | } |
| 91 | 103 | ||
| 92 | static inline void write_cr3(unsigned long val) | 104 | static inline void write_cr3(unsigned long val) |
| 93 | { | 105 | { |
| @@ -99,12 +111,24 @@ static inline unsigned long read_cr4(void) | |||
| 99 | unsigned long cr4; | 111 | unsigned long cr4; |
| 100 | asm("movq %%cr4,%0" : "=r" (cr4)); | 112 | asm("movq %%cr4,%0" : "=r" (cr4)); |
| 101 | return cr4; | 113 | return cr4; |
| 102 | } | 114 | } |
| 103 | 115 | ||
| 104 | static inline void write_cr4(unsigned long val) | 116 | static inline void write_cr4(unsigned long val) |
| 105 | { | 117 | { |
| 106 | asm volatile("movq %0,%%cr4" :: "r" (val) : "memory"); | 118 | asm volatile("movq %0,%%cr4" :: "r" (val) : "memory"); |
| 107 | } | 119 | } |
| 120 | |||
| 121 | static inline unsigned long read_cr8(void) | ||
| 122 | { | ||
| 123 | unsigned long cr8; | ||
| 124 | asm("movq %%cr8,%0" : "=r" (cr8)); | ||
| 125 | return cr8; | ||
| 126 | } | ||
| 127 | |||
| 128 | static inline void write_cr8(unsigned long val) | ||
| 129 | { | ||
| 130 | asm volatile("movq %0,%%cr8" :: "r" (val) : "memory"); | ||
| 131 | } | ||
| 108 | 132 | ||
| 109 | #define stts() write_cr0(8 | read_cr0()) | 133 | #define stts() write_cr0(8 | read_cr0()) |
| 110 | 134 | ||
diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h index 5fd44e63fb26..448f70b30a0c 100644 --- a/include/linux/of_platform.h +++ b/include/linux/of_platform.h | |||
| @@ -31,8 +31,8 @@ extern struct bus_type of_platform_bus_type; | |||
| 31 | */ | 31 | */ |
| 32 | struct of_platform_driver | 32 | struct of_platform_driver |
| 33 | { | 33 | { |
| 34 | char *name; | 34 | const char *name; |
| 35 | struct of_device_id *match_table; | 35 | const struct of_device_id *match_table; |
| 36 | struct module *owner; | 36 | struct module *owner; |
| 37 | 37 | ||
| 38 | int (*probe)(struct of_device* dev, | 38 | int (*probe)(struct of_device* dev, |
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index b15c6498fe67..ced4d3f76104 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h | |||
| @@ -2040,6 +2040,8 @@ | |||
| 2040 | #define PCI_DEVICE_ID_ALTIMA_AC9100 0x03ea | 2040 | #define PCI_DEVICE_ID_ALTIMA_AC9100 0x03ea |
| 2041 | #define PCI_DEVICE_ID_ALTIMA_AC1003 0x03eb | 2041 | #define PCI_DEVICE_ID_ALTIMA_AC1003 0x03eb |
| 2042 | 2042 | ||
| 2043 | #define PCI_VENDOR_ID_LENOVO 0x17aa | ||
| 2044 | |||
| 2043 | #define PCI_VENDOR_ID_ARECA 0x17d3 | 2045 | #define PCI_VENDOR_ID_ARECA 0x17d3 |
| 2044 | #define PCI_DEVICE_ID_ARECA_1110 0x1110 | 2046 | #define PCI_DEVICE_ID_ARECA_1110 0x1110 |
| 2045 | #define PCI_DEVICE_ID_ARECA_1120 0x1120 | 2047 | #define PCI_DEVICE_ID_ARECA_1120 0x1120 |
diff --git a/include/linux/signal.h b/include/linux/signal.h index ea91abe740da..0ae338866240 100644 --- a/include/linux/signal.h +++ b/include/linux/signal.h | |||
| @@ -237,12 +237,15 @@ extern int group_send_sig_info(int sig, struct siginfo *info, struct task_struct | |||
| 237 | extern int __group_send_sig_info(int, struct siginfo *, struct task_struct *); | 237 | extern int __group_send_sig_info(int, struct siginfo *, struct task_struct *); |
| 238 | extern long do_sigpending(void __user *, unsigned long); | 238 | extern long do_sigpending(void __user *, unsigned long); |
| 239 | extern int sigprocmask(int, sigset_t *, sigset_t *); | 239 | extern int sigprocmask(int, sigset_t *, sigset_t *); |
| 240 | extern int show_unhandled_signals; | ||
| 240 | 241 | ||
| 241 | struct pt_regs; | 242 | struct pt_regs; |
| 242 | extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie); | 243 | extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie); |
| 243 | 244 | ||
| 244 | extern struct kmem_cache *sighand_cachep; | 245 | extern struct kmem_cache *sighand_cachep; |
| 245 | 246 | ||
| 247 | int unhandled_signal(struct task_struct *tsk, int sig); | ||
| 248 | |||
| 246 | /* | 249 | /* |
| 247 | * In POSIX a signal is sent either to a specific thread (Linux task) | 250 | * In POSIX a signal is sent either to a specific thread (Linux task) |
| 248 | * or to the process as a whole (Linux thread group). How the signal | 251 | * or to the process as a whole (Linux thread group). How the signal |
diff --git a/kernel/signal.c b/kernel/signal.c index 39d122753bac..ef8156a6aad5 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
| @@ -255,6 +255,16 @@ flush_signal_handlers(struct task_struct *t, int force_default) | |||
| 255 | } | 255 | } |
| 256 | } | 256 | } |
| 257 | 257 | ||
| 258 | int unhandled_signal(struct task_struct *tsk, int sig) | ||
| 259 | { | ||
| 260 | if (is_init(tsk)) | ||
| 261 | return 1; | ||
| 262 | if (tsk->ptrace & PT_PTRACED) | ||
| 263 | return 0; | ||
| 264 | return (tsk->sighand->action[sig-1].sa.sa_handler == SIG_IGN) || | ||
| 265 | (tsk->sighand->action[sig-1].sa.sa_handler == SIG_DFL); | ||
| 266 | } | ||
| 267 | |||
| 258 | 268 | ||
| 259 | /* Notify the system that a driver wants to block all signals for this | 269 | /* Notify the system that a driver wants to block all signals for this |
| 260 | * process, and wants to be notified if any signals at all were to be | 270 | * process, and wants to be notified if any signals at all were to be |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 222299844ad1..ddebf3f2affe 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
| @@ -1203,6 +1203,16 @@ static ctl_table fs_table[] = { | |||
| 1203 | }; | 1203 | }; |
| 1204 | 1204 | ||
| 1205 | static ctl_table debug_table[] = { | 1205 | static ctl_table debug_table[] = { |
| 1206 | #ifdef CONFIG_X86 | ||
| 1207 | { | ||
| 1208 | .ctl_name = CTL_UNNUMBERED, | ||
| 1209 | .procname = "exception-trace", | ||
| 1210 | .data = &show_unhandled_signals, | ||
| 1211 | .maxlen = sizeof(int), | ||
| 1212 | .mode = 0644, | ||
| 1213 | .proc_handler = proc_dointvec | ||
| 1214 | }, | ||
| 1215 | #endif | ||
| 1206 | { .ctl_name = 0 } | 1216 | { .ctl_name = 0 } |
| 1207 | }; | 1217 | }; |
| 1208 | 1218 | ||
diff --git a/mm/sparse.c b/mm/sparse.c index e03b39f3540f..3047bf06c1f3 100644 --- a/mm/sparse.c +++ b/mm/sparse.c | |||
| @@ -209,7 +209,7 @@ static int __meminit sparse_init_one_section(struct mem_section *ms, | |||
| 209 | return 1; | 209 | return 1; |
| 210 | } | 210 | } |
| 211 | 211 | ||
| 212 | __attribute__((weak)) | 212 | __attribute__((weak)) __init |
| 213 | void *alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size) | 213 | void *alloc_bootmem_high_node(pg_data_t *pgdat, unsigned long size) |
| 214 | { | 214 | { |
| 215 | return NULL; | 215 | return NULL; |
