From a4660e61fe55eff55cd15e5ec02522bcd3e3b43d Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Fri, 25 Jan 2008 14:47:49 +0800 Subject: [PATCH] --- yaml --- r: 84155 b: refs/heads/master c: 8a681a4dee07ea09aedaadc6a2da28d2131dc414 h: refs/heads/master i: 84153: 1bdb6348009457f0f8fd550ce1c70cd21fad5d05 84151: 6e0768023be08ce1d4c47249ba07bd94de54e226 v: v3 --- [refs] | 2 +- trunk/Documentation/00-INDEX | 3 - .../ABI/testing/sysfs-firmware-acpi | 99 - trunk/Documentation/acpi/method-tracing.txt | 26 - trunk/Documentation/kernel-parameters.txt | 6 +- trunk/Documentation/power/swsusp.txt | 5 - trunk/Documentation/thermal/sysfs-api.txt | 246 -- trunk/Documentation/thinkpad-acpi.txt | 116 +- trunk/MAINTAINERS | 19 - trunk/arch/ia64/kernel/acpi.c | 28 +- trunk/arch/x86/Kconfig | 6 - trunk/arch/x86/kernel/acpi/boot.c | 44 +- .../x86/kernel/cpu/cpufreq/speedstep-lib.c | 5 +- trunk/arch/x86/kernel/srat_32.c | 2 +- trunk/drivers/Kconfig | 2 - trunk/drivers/Makefile | 1 - trunk/drivers/acpi/Kconfig | 11 - trunk/drivers/acpi/Makefile | 1 - trunk/drivers/acpi/asus_acpi.c | 55 +- trunk/drivers/acpi/battery.c | 5 - trunk/drivers/acpi/bay.c | 6 - trunk/drivers/acpi/blacklist.c | 58 +- trunk/drivers/acpi/bus.c | 25 - trunk/drivers/acpi/debug.c | 57 - trunk/drivers/acpi/dock.c | 6 - trunk/drivers/acpi/ec.c | 19 +- trunk/drivers/acpi/events/evevent.c | 2 +- trunk/drivers/acpi/events/evgpe.c | 27 +- trunk/drivers/acpi/fan.c | 92 +- trunk/drivers/acpi/hardware/hwsleep.c | 2 +- trunk/drivers/acpi/namespace/nsxfeval.c | 10 +- trunk/drivers/acpi/osl.c | 81 +- trunk/drivers/acpi/pci_irq.c | 5 +- trunk/drivers/acpi/power.c | 6 +- trunk/drivers/acpi/processor_core.c | 40 +- trunk/drivers/acpi/processor_idle.c | 47 +- trunk/drivers/acpi/processor_perflib.c | 16 +- trunk/drivers/acpi/processor_thermal.c | 134 +- trunk/drivers/acpi/scan.c | 100 +- trunk/drivers/acpi/sleep/main.c | 17 +- trunk/drivers/acpi/sleep/proc.c | 46 +- trunk/drivers/acpi/system.c | 208 - trunk/drivers/acpi/tables/Makefile | 2 +- trunk/drivers/acpi/tables/tbxfroot.c | 4 +- trunk/drivers/acpi/thermal.c | 663 +-- trunk/drivers/acpi/utilities/utglobal.c | 2 + trunk/drivers/acpi/video.c | 145 +- trunk/drivers/acpi/wmi.c | 710 ---- trunk/drivers/cpuidle/Kconfig | 4 +- trunk/drivers/cpuidle/cpuidle.c | 43 +- trunk/drivers/firmware/dmi_scan.c | 9 + trunk/drivers/misc/Kconfig | 53 - trunk/drivers/misc/Makefile | 3 - trunk/drivers/misc/acer-wmi.c | 1109 ----- trunk/drivers/misc/asus-laptop.c | 26 +- trunk/drivers/misc/intel_menlow.c | 526 --- trunk/drivers/misc/sony-laptop.c | 445 +- trunk/drivers/misc/tc1100-wmi.c | 290 -- trunk/drivers/misc/thinkpad_acpi.c | 3778 ++++++----------- trunk/drivers/misc/thinkpad_acpi.h | 606 +++ trunk/drivers/pnp/pnpacpi/core.c | 2 +- trunk/drivers/power/power_supply_sysfs.c | 1 - trunk/drivers/thermal/Kconfig | 15 - trunk/drivers/thermal/Makefile | 5 - trunk/drivers/thermal/thermal.c | 714 ---- trunk/include/acpi/acglobal.h | 4 + trunk/include/acpi/acpi_bus.h | 2 - trunk/include/acpi/acpi_drivers.h | 1 - trunk/include/acpi/acpiosxf.h | 3 - trunk/include/acpi/processor.h | 9 +- trunk/include/linux/acpi.h | 23 +- trunk/include/linux/cpuidle.h | 26 +- trunk/include/linux/dmi.h | 2 + trunk/include/linux/power_supply.h | 1 - trunk/include/linux/sonypi.h | 2 - trunk/include/linux/thermal.h | 94 - trunk/kernel/power/Kconfig | 9 +- 77 files changed, 2599 insertions(+), 8418 deletions(-) delete mode 100644 trunk/Documentation/ABI/testing/sysfs-firmware-acpi delete mode 100644 trunk/Documentation/acpi/method-tracing.txt delete mode 100644 trunk/Documentation/thermal/sysfs-api.txt delete mode 100644 trunk/drivers/acpi/wmi.c delete mode 100644 trunk/drivers/misc/acer-wmi.c delete mode 100644 trunk/drivers/misc/intel_menlow.c delete mode 100644 trunk/drivers/misc/tc1100-wmi.c create mode 100644 trunk/drivers/misc/thinkpad_acpi.h delete mode 100644 trunk/drivers/thermal/Kconfig delete mode 100644 trunk/drivers/thermal/Makefile delete mode 100644 trunk/drivers/thermal/thermal.c delete mode 100644 trunk/include/linux/thermal.h diff --git a/[refs] b/[refs] index 97c3cc310010..7aadcb202104 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 060195500e0347a6ba8ea89739a9898961eb6f2b +refs/heads/master: 8a681a4dee07ea09aedaadc6a2da28d2131dc414 diff --git a/trunk/Documentation/00-INDEX b/trunk/Documentation/00-INDEX index 33f55917f23f..40ac7759c3bb 100644 --- a/trunk/Documentation/00-INDEX +++ b/trunk/Documentation/00-INDEX @@ -14,7 +14,6 @@ Following translations are available on the WWW: - this file. ABI/ - info on kernel <-> userspace ABI and relative interface stability. - BUG-HUNTING - brute force method of doing binary search of patches to find bug. Changes @@ -67,8 +66,6 @@ VGA-softcursor.txt - how to change your VGA cursor from a blinking underscore. accounting/ - documentation on accounting and taskstats. -acpi/ - - info on ACPI-specific hooks in the kernel. aoe/ - description of AoE (ATA over Ethernet) along with config examples. applying-patches.txt diff --git a/trunk/Documentation/ABI/testing/sysfs-firmware-acpi b/trunk/Documentation/ABI/testing/sysfs-firmware-acpi deleted file mode 100644 index 9470ed9afcc0..000000000000 --- a/trunk/Documentation/ABI/testing/sysfs-firmware-acpi +++ /dev/null @@ -1,99 +0,0 @@ -What: /sys/firmware/acpi/interrupts/ -Date: February 2008 -Contact: Len Brown -Description: - All ACPI interrupts are handled via a single IRQ, - the System Control Interrupt (SCI), which appears - as "acpi" in /proc/interrupts. - - However, one of the main functions of ACPI is to make - the platform understand random hardware without - special driver support. So while the SCI handles a few - well known (fixed feature) interrupts sources, such - as the power button, it can also handle a variable - number of a "General Purpose Events" (GPE). - - A GPE vectors to a specified handler in AML, which - can do a anything the BIOS writer wants from - OS context. GPE 0x12, for example, would vector - to a level or edge handler called _L12 or _E12. - The handler may do its business and return. - Or the handler may send send a Notify event - to a Linux device driver registered on an ACPI device, - such as a battery, or a processor. - - To figure out where all the SCI's are coming from, - /sys/firmware/acpi/interrupts contains a file listing - every possible source, and the count of how many - times it has triggered. - - $ cd /sys/firmware/acpi/interrupts - $ grep . * - error:0 - ff_gbl_lock:0 - ff_pmtimer:0 - ff_pwr_btn:0 - ff_rt_clk:0 - ff_slp_btn:0 - gpe00:0 - gpe01:0 - gpe02:0 - gpe03:0 - gpe04:0 - gpe05:0 - gpe06:0 - gpe07:0 - gpe08:0 - gpe09:174 - gpe0A:0 - gpe0B:0 - gpe0C:0 - gpe0D:0 - gpe0E:0 - gpe0F:0 - gpe10:0 - gpe11:60 - gpe12:0 - gpe13:0 - gpe14:0 - gpe15:0 - gpe16:0 - gpe17:0 - gpe18:0 - gpe19:7 - gpe1A:0 - gpe1B:0 - gpe1C:0 - gpe1D:0 - gpe1E:0 - gpe1F:0 - gpe_all:241 - sci:241 - - sci - The total number of times the ACPI SCI - has claimed an interrupt. - - gpe_all - count of SCI caused by GPEs. - - gpeXX - count for individual GPE source - - ff_gbl_lock - Global Lock - - ff_pmtimer - PM Timer - - ff_pwr_btn - Power Button - - ff_rt_clk - Real Time Clock - - ff_slp_btn - Sleep Button - - error - an interrupt that can't be accounted for above. - - Root has permission to clear any of these counters. Eg. - # echo 0 > gpe11 - - All counters can be cleared by clearing the total "sci": - # echo 0 > sci - - None of these counters has an effect on the function - of the system, they are simply statistics. diff --git a/trunk/Documentation/acpi/method-tracing.txt b/trunk/Documentation/acpi/method-tracing.txt deleted file mode 100644 index f6efb1ea559a..000000000000 --- a/trunk/Documentation/acpi/method-tracing.txt +++ /dev/null @@ -1,26 +0,0 @@ -/sys/module/acpi/parameters/: - -trace_method_name - The AML method name that the user wants to trace - -trace_debug_layer - The temporary debug_layer used when tracing the method. - Using 0xffffffff by default if it is 0. - -trace_debug_level - The temporary debug_level used when tracing the method. - Using 0x00ffffff by default if it is 0. - -trace_state - The status of the tracing feature. - - "enabled" means this feature is enabled - and the AML method is traced every time it's executed. - - "1" means this feature is enabled and the AML method - will only be traced during the next execution. - - "disabled" means this feature is disabled. - Users can enable/disable this debug tracing feature by - "echo string > /sys/module/acpi/parameters/trace_state". - "string" should be one of "enable", "disable" and "1". diff --git a/trunk/Documentation/kernel-parameters.txt b/trunk/Documentation/kernel-parameters.txt index 8ea41b6e6a85..8fd5aa40585f 100644 --- a/trunk/Documentation/kernel-parameters.txt +++ b/trunk/Documentation/kernel-parameters.txt @@ -147,10 +147,8 @@ and is between 256 and 4096 characters. It is defined in the file default: 0 acpi_sleep= [HW,ACPI] Sleep options - Format: { s3_bios, s3_mode, s3_beep } - See Documentation/power/video.txt for s3_bios and s3_mode. - s3_beep is for debugging; it makes the PC's speaker beep - as soon as the kernel's real-mode entry point is called. + Format: { s3_bios, s3_mode } + See Documentation/power/video.txt acpi_sci= [HW,ACPI] ACPI System Control Interrupt trigger mode Format: { level | edge | high | low } diff --git a/trunk/Documentation/power/swsusp.txt b/trunk/Documentation/power/swsusp.txt index 9d60ab717a7b..aea7e9209667 100644 --- a/trunk/Documentation/power/swsusp.txt +++ b/trunk/Documentation/power/swsusp.txt @@ -386,11 +386,6 @@ before suspending; then remount them after resuming. There is a work-around for this problem. For more information, see Documentation/usb/persist.txt. -Q: Can I suspend-to-disk using a swap partition under LVM? - -A: No. You can suspend successfully, but you'll not be able to -resume. uswsusp should be able to work with LVM. See suspend.sf.net. - Q: I upgraded the kernel from 2.6.15 to 2.6.16. Both kernels were compiled with the similar configuration files. Anyway I found that suspend to disk (and resume) is much slower on 2.6.16 compared to diff --git a/trunk/Documentation/thermal/sysfs-api.txt b/trunk/Documentation/thermal/sysfs-api.txt deleted file mode 100644 index 5776e090359d..000000000000 --- a/trunk/Documentation/thermal/sysfs-api.txt +++ /dev/null @@ -1,246 +0,0 @@ -Generic Thermal Sysfs driver How To -========================= - -Written by Sujith Thomas , Zhang Rui - -Updated: 2 January 2008 - -Copyright (c) 2008 Intel Corporation - - -0. Introduction - -The generic thermal sysfs provides a set of interfaces for thermal zone devices (sensors) -and thermal cooling devices (fan, processor...) to register with the thermal management -solution and to be a part of it. - -This how-to focusses on enabling new thermal zone and cooling devices to participate -in thermal management. -This solution is platform independent and any type of thermal zone devices and -cooling devices should be able to make use of the infrastructure. - -The main task of the thermal sysfs driver is to expose thermal zone attributes as well -as cooling device attributes to the user space. -An intelligent thermal management application can make decisions based on inputs -from thermal zone attributes (the current temperature and trip point temperature) -and throttle appropriate devices. - -[0-*] denotes any positive number starting from 0 -[1-*] denotes any positive number starting from 1 - -1. thermal sysfs driver interface functions - -1.1 thermal zone device interface -1.1.1 struct thermal_zone_device *thermal_zone_device_register(char *name, int trips, - void *devdata, struct thermal_zone_device_ops *ops) - - This interface function adds a new thermal zone device (sensor) to - /sys/class/thermal folder as thermal_zone[0-*]. - It tries to bind all the thermal cooling devices registered at the same time. - - name: the thermal zone name. - trips: the total number of trip points this thermal zone supports. - devdata: device private data - ops: thermal zone device callbacks. - .bind: bind the thermal zone device with a thermal cooling device. - .unbind: unbing the thermal zone device with a thermal cooling device. - .get_temp: get the current temperature of the thermal zone. - .get_mode: get the current mode (user/kernel) of the thermal zone. - "kernel" means thermal management is done in kernel. - "user" will prevent kernel thermal driver actions upon trip points - so that user applications can take charge of thermal management. - .set_mode: set the mode (user/kernel) of the thermal zone. - .get_trip_type: get the type of certain trip point. - .get_trip_temp: get the temperature above which the certain trip point - will be fired. - -1.1.2 void thermal_zone_device_unregister(struct thermal_zone_device *tz) - - This interface function removes the thermal zone device. - It deletes the corresponding entry form /sys/class/thermal folder and unbind all - the thermal cooling devices it uses. - -1.2 thermal cooling device interface -1.2.1 struct thermal_cooling_device *thermal_cooling_device_register(char *name, - void *devdata, struct thermal_cooling_device_ops *) - - This interface function adds a new thermal cooling device (fan/processor/...) to - /sys/class/thermal/ folder as cooling_device[0-*]. - It tries to bind itself to all the thermal zone devices register at the same time. - name: the cooling device name. - devdata: device private data. - ops: thermal cooling devices callbacks. - .get_max_state: get the Maximum throttle state of the cooling device. - .get_cur_state: get the Current throttle state of the cooling device. - .set_cur_state: set the Current throttle state of the cooling device. - -1.2.2 void thermal_cooling_device_unregister(struct thermal_cooling_device *cdev) - - This interface function remove the thermal cooling device. - It deletes the corresponding entry form /sys/class/thermal folder and unbind - itself from all the thermal zone devices using it. - -1.3 interface for binding a thermal zone device with a thermal cooling device -1.3.1 int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, - int trip, struct thermal_cooling_device *cdev); - - This interface function bind a thermal cooling device to the certain trip point - of a thermal zone device. - This function is usually called in the thermal zone device .bind callback. - tz: the thermal zone device - cdev: thermal cooling device - trip: indicates which trip point the cooling devices is associated with - in this thermal zone. - -1.3.2 int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz, - int trip, struct thermal_cooling_device *cdev); - - This interface function unbind a thermal cooling device from the certain trip point - of a thermal zone device. - This function is usually called in the thermal zone device .unbind callback. - tz: the thermal zone device - cdev: thermal cooling device - trip: indicates which trip point the cooling devices is associated with - in this thermal zone. - -2. sysfs attributes structure - -RO read only value -RW read/write value - -All thermal sysfs attributes will be represented under /sys/class/thermal -/sys/class/thermal/ - -Thermal zone device sys I/F, created once it's registered: -|thermal_zone[0-*]: - |-----type: Type of the thermal zone - |-----temp: Current temperature - |-----mode: Working mode of the thermal zone - |-----trip_point_[0-*]_temp: Trip point temperature - |-----trip_point_[0-*]_type: Trip point type - -Thermal cooling device sys I/F, created once it's registered: -|cooling_device[0-*]: - |-----type : Type of the cooling device(processor/fan/...) - |-----max_state: Maximum cooling state of the cooling device - |-----cur_state: Current cooling state of the cooling device - - -These two dynamic attributes are created/removed in pairs. -They represent the relationship between a thermal zone and its associated cooling device. -They are created/removed for each -thermal_zone_bind_cooling_device/thermal_zone_unbind_cooling_device successful exection. - -|thermal_zone[0-*] - |-----cdev[0-*]: The [0-*]th cooling device in the current thermal zone - |-----cdev[0-*]_trip_point: Trip point that cdev[0-*] is associated with - - -*************************** -* Thermal zone attributes * -*************************** - -type Strings which represent the thermal zone type. - This is given by thermal zone driver as part of registration. - Eg: "ACPI thermal zone" indicates it's a ACPI thermal device - RO - Optional - -temp Current temperature as reported by thermal zone (sensor) - Unit: degree celsius - RO - Required - -mode One of the predifned values in [kernel, user] - This file gives information about the algorithm - that is currently managing the thermal zone. - It can be either default kernel based algorithm - or user space application. - RW - Optional - kernel = Thermal management in kernel thermal zone driver. - user = Preventing kernel thermal zone driver actions upon - trip points so that user application can take full - charge of the thermal management. - -trip_point_[0-*]_temp The temperature above which trip point will be fired - Unit: degree celsius - RO - Optional - -trip_point_[0-*]_type Strings which indicate the type of the trip point - Eg. it can be one of critical, hot, passive, - active[0-*] for ACPI thermal zone. - RO - Optional - -cdev[0-*] Sysfs link to the thermal cooling device node where the sys I/F - for cooling device throttling control represents. - RO - Optional - -cdev[0-*]_trip_point The trip point with which cdev[0-*] is assocated in this thermal zone - -1 means the cooling device is not associated with any trip point. - RO - Optional - -****************************** -* Cooling device attributes * -****************************** - -type String which represents the type of device - eg: For generic ACPI: this should be "Fan", - "Processor" or "LCD" - eg. For memory controller device on intel_menlow platform: - this should be "Memory controller" - RO - Optional - -max_state The maximum permissible cooling state of this cooling device. - RO - Required - -cur_state The current cooling state of this cooling device. - the value can any integer numbers between 0 and max_state, - cur_state == 0 means no cooling - cur_state == max_state means the maximum cooling. - RW - Required - -3. A simple implementation - -ACPI thermal zone may support multiple trip points like critical/hot/passive/active. -If an ACPI thermal zone supports critical, passive, active[0] and active[1] at the same time, -it may register itself as a thermale_zone_device (thermal_zone1) with 4 trip points in all. -It has one processor and one fan, which are both registered as thermal_cooling_device. -If the processor is listed in _PSL method, and the fan is listed in _AL0 method, -the sys I/F structure will be built like this: - -/sys/class/thermal: - -|thermal_zone1: - |-----type: ACPI thermal zone - |-----temp: 37 - |-----mode: kernel - |-----trip_point_0_temp: 100 - |-----trip_point_0_type: critical - |-----trip_point_1_temp: 80 - |-----trip_point_1_type: passive - |-----trip_point_2_temp: 70 - |-----trip_point_2_type: active[0] - |-----trip_point_3_temp: 60 - |-----trip_point_3_type: active[1] - |-----cdev0: --->/sys/class/thermal/cooling_device0 - |-----cdev0_trip_point: 1 /* cdev0 can be used for passive */ - |-----cdev1: --->/sys/class/thermal/cooling_device3 - |-----cdev1_trip_point: 2 /* cdev1 can be used for active[0]*/ - -|cooling_device0: - |-----type: Processor - |-----max_state: 8 - |-----cur_state: 0 - -|cooling_device3: - |-----type: Fan - |-----max_state: 2 - |-----cur_state: 0 diff --git a/trunk/Documentation/thinkpad-acpi.txt b/trunk/Documentation/thinkpad-acpi.txt index 6c2477754a2a..10c041ca13c7 100644 --- a/trunk/Documentation/thinkpad-acpi.txt +++ b/trunk/Documentation/thinkpad-acpi.txt @@ -1,7 +1,7 @@ ThinkPad ACPI Extras Driver - Version 0.19 - January 06th, 2008 + Version 0.17 + October 04th, 2007 Borislav Deianov Henrique de Moraes Holschuh @@ -215,11 +215,6 @@ The following commands can be written to the /proc/acpi/ibm/hotkey file: ... any other 8-hex-digit mask ... echo reset > /proc/acpi/ibm/hotkey -- restore the original mask -The procfs interface does not support NVRAM polling control. So as to -maintain maximum bug-to-bug compatibility, it does not report any masks, -nor does it allow one to manipulate the hot key mask when the firmware -does not support masks at all, even if NVRAM polling is in use. - sysfs notes: hotkey_bios_enabled: @@ -236,26 +231,17 @@ sysfs notes: to this value. hotkey_enable: - Enables/disables the hot keys feature in the ACPI - firmware, and reports current status of the hot keys - feature. Has no effect on the NVRAM hot key polling - functionality. + Enables/disables the hot keys feature, and reports + current status of the hot keys feature. 0: disables the hot keys feature / feature disabled 1: enables the hot keys feature / feature enabled hotkey_mask: - bit mask to enable driver-handling (and depending on - the firmware, ACPI event generation) for each hot key - (see above). Returns the current status of the hot keys - mask, and allows one to modify it. - - Note: when NVRAM polling is active, the firmware mask - will be different from the value returned by - hotkey_mask. The driver will retain enabled bits for - hotkeys that are under NVRAM polling even if the - firmware refuses them, and will not set these bits on - the firmware hot key mask. + bit mask to enable driver-handling and ACPI event + generation for each hot key (see above). Returns the + current status of the hot keys mask, and allows one to + modify it. hotkey_all_mask: bit mask that should enable event reporting for all @@ -271,48 +257,12 @@ sysfs notes: handled by the firmware anyway. Echo it to hotkey_mask above, to use. - hotkey_source_mask: - bit mask that selects which hot keys will the driver - poll the NVRAM for. This is auto-detected by the driver - based on the capabilities reported by the ACPI firmware, - but it can be overridden at runtime. - - Hot keys whose bits are set in both hotkey_source_mask - and also on hotkey_mask are polled for in NVRAM. Only a - few hot keys are available through CMOS NVRAM polling. - - Warning: when in NVRAM mode, the volume up/down/mute - keys are synthesized according to changes in the mixer, - so you have to use volume up or volume down to unmute, - as per the ThinkPad volume mixer user interface. When - in ACPI event mode, volume up/down/mute are reported as - separate events, but this behaviour may be corrected in - future releases of this driver, in which case the - ThinkPad volume mixer user interface semanthics will be - enforced. - - hotkey_poll_freq: - frequency in Hz for hot key polling. It must be between - 0 and 25 Hz. Polling is only carried out when strictly - needed. - - Setting hotkey_poll_freq to zero disables polling, and - will cause hot key presses that require NVRAM polling - to never be reported. - - Setting hotkey_poll_freq too low will cause repeated - pressings of the same hot key to be misreported as a - single key press, or to not even be detected at all. - The recommended polling frequency is 10Hz. - hotkey_radio_sw: if the ThinkPad has a hardware radio switch, this attribute will read 0 if the switch is in the "radios disabled" postition, and 1 if the switch is in the "radios enabled" position. - This attribute has poll()/select() support. - hotkey_report_mode: Returns the state of the procfs ACPI event report mode filter for hot keys. If it is set to 1 (the default), @@ -327,25 +277,6 @@ sysfs notes: May return -EPERM (write access locked out by module parameter) or -EACCES (read-only). - wakeup_reason: - Set to 1 if the system is waking up because the user - requested a bay ejection. Set to 2 if the system is - waking up because the user requested the system to - undock. Set to zero for normal wake-ups or wake-ups - due to unknown reasons. - - This attribute has poll()/select() support. - - wakeup_hotunplug_complete: - Set to 1 if the system was waken up because of an - undock or bay ejection request, and that request - was sucessfully completed. At this point, it might - be useful to send the system back to sleep, at the - user's choice. Refer to HKEY events 0x4003 and - 0x3003, below. - - This attribute has poll()/select() support. - input layer notes: A Hot key is mapped to a single input layer EV_KEY event, possibly @@ -496,23 +427,6 @@ Non hot-key ACPI HKEY event map: The above events are not propagated by the driver, except for legacy compatibility purposes when hotkey_report_mode is set to 1. -0x2304 System is waking up from suspend to undock -0x2305 System is waking up from suspend to eject bay -0x2404 System is waking up from hibernation to undock -0x2405 System is waking up from hibernation to eject bay - -The above events are never propagated by the driver. - -0x3003 Bay ejection (see 0x2x05) complete, can sleep again -0x4003 Undocked (see 0x2x04), can sleep again -0x5009 Tablet swivel: switched to tablet mode -0x500A Tablet swivel: switched to normal mode -0x500B Tablet pen insterted into its storage bay -0x500C Tablet pen removed from its storage bay -0x5010 Brightness level changed (newer Lenovo BIOSes) - -The above events are propagated by the driver. - Compatibility notes: ibm-acpi and thinkpad-acpi 0.15 (mainline kernels before 2.6.23) never @@ -1349,17 +1263,3 @@ Sysfs interface changelog: and the hwmon class for libsensors4 (lm-sensors 3) compatibility. Moved all hwmon attributes to this new platform device. - -0x020100: Marker for thinkpad-acpi with hot key NVRAM polling - support. If you must, use it to know you should not - start an userspace NVRAM poller (allows to detect when - NVRAM is compiled out by the user because it is - unneeded/undesired in the first place). -0x020101: Marker for thinkpad-acpi with hot key NVRAM polling - and proper hotkey_mask semanthics (version 8 of the - NVRAM polling patch). Some development snapshots of - 0.18 had an earlier version that did strange things - to hotkey_mask. - -0x020200: Add poll()/select() support to the following attributes: - hotkey_radio_sw, wakeup_hotunplug_complete, wakeup_reason diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 0819a579005c..0885aa2b095a 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -202,13 +202,6 @@ L: linux-scsi@vger.kernel.org W: http://www.adaptec.com/ S: Supported -ACER WMI LAPTOP EXTRAS -P: Carlos Corbacho -M: carlos@strangeworlds.co.uk -L: aceracpi@googlegroups.com (subscribers-only) -W: http://code.google.com/p/aceracpi -S: Maintained - ACPI P: Len Brown M: len.brown@intel.com @@ -259,13 +252,6 @@ L: linux-acpi@vger.kernel.org W: http://acpi.sourceforge.net/ S: Supported -ACPI WMI DRIVER -P: Carlos Corbacho -M: carlos@strangeworlds.co.uk -L: linux-acpi@vger.kernel.org -W: http://www.lesswatts.org/projects/acpi/ -S: Maintained - ADM1025 HARDWARE MONITOR DRIVER P: Jean Delvare M: khali@linux-fr.org @@ -1799,11 +1785,6 @@ P: Jaroslav Kysela M: perex@perex.cz S: Maintained -HP COMPAQ TC1100 TABLET WMI EXTRAS DRIVER -P: Carlos Corbacho -M: carlos@strangeworlds.co.uk -S: Odd Fixes - HPET: High Precision Event Timers driver (hpet.c) P: Clemens Ladisch M: clemens@ladisch.de diff --git a/trunk/arch/ia64/kernel/acpi.c b/trunk/arch/ia64/kernel/acpi.c index 90680255032e..00b5d08f6da8 100644 --- a/trunk/arch/ia64/kernel/acpi.c +++ b/trunk/arch/ia64/kernel/acpi.c @@ -69,20 +69,6 @@ unsigned int acpi_cpei_phys_cpuid; unsigned long acpi_wakeup_address = 0; -#ifdef CONFIG_IA64_GENERIC -static unsigned long __init acpi_find_rsdp(void) -{ - unsigned long rsdp_phys = 0; - - if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) - rsdp_phys = efi.acpi20; - else if (efi.acpi != EFI_INVALID_TABLE_ADDR) - printk(KERN_WARNING PREFIX - "v1.0/r0.71 tables no longer supported\n"); - return rsdp_phys; -} -#endif - const char __init * acpi_get_sysname(void) { @@ -166,7 +152,7 @@ int acpi_request_vector(u32 int_type) return vector; } -char *__init __acpi_map_table(unsigned long phys_addr, unsigned long size) +char *__acpi_map_table(unsigned long phys_addr, unsigned long size) { return __va(phys_addr); } @@ -645,6 +631,18 @@ static int __init acpi_parse_fadt(struct acpi_table_header *table) return 0; } +unsigned long __init acpi_find_rsdp(void) +{ + unsigned long rsdp_phys = 0; + + if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) + rsdp_phys = efi.acpi20; + else if (efi.acpi != EFI_INVALID_TABLE_ADDR) + printk(KERN_WARNING PREFIX + "v1.0/r0.71 tables no longer supported\n"); + return rsdp_phys; +} + int __init acpi_boot_init(void) { diff --git a/trunk/arch/x86/Kconfig b/trunk/arch/x86/Kconfig index 3954ae96b0c7..e6728bd61cc1 100644 --- a/trunk/arch/x86/Kconfig +++ b/trunk/arch/x86/Kconfig @@ -98,9 +98,6 @@ config ARCH_HAS_ILOG2_U32 config ARCH_HAS_ILOG2_U64 def_bool n -config ARCH_HAS_CPU_IDLE_WAIT - def_bool y - config GENERIC_CALIBRATE_DELAY def_bool y @@ -108,9 +105,6 @@ config GENERIC_TIME_VSYSCALL bool default X86_64 -config ARCH_HAS_CPU_RELAX - def_bool y - config HAVE_SETUP_PER_CPU_AREA def_bool X86_64 diff --git a/trunk/arch/x86/kernel/acpi/boot.c b/trunk/arch/x86/kernel/acpi/boot.c index f3e049ea86eb..d2a58431a074 100644 --- a/trunk/arch/x86/kernel/acpi/boot.c +++ b/trunk/arch/x86/kernel/acpi/boot.c @@ -106,7 +106,7 @@ enum acpi_irq_model_id acpi_irq_model = ACPI_IRQ_MODEL_PIC; #ifdef CONFIG_X86_64 /* rely on all ACPI tables being in the direct mapping */ -char *__init __acpi_map_table(unsigned long phys_addr, unsigned long size) +char *__acpi_map_table(unsigned long phys_addr, unsigned long size) { if (!phys_addr || !size) return NULL; @@ -131,7 +131,7 @@ char *__init __acpi_map_table(unsigned long phys_addr, unsigned long size) * from the fixed base. That's why we start at FIX_IO_APIC_BASE_END and * count idx down while incrementing the phys address. */ -char *__init __acpi_map_table(unsigned long phys, unsigned long size) +char *__acpi_map_table(unsigned long phys, unsigned long size) { unsigned long base, offset, mapped_size; int idx; @@ -587,6 +587,25 @@ int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base) EXPORT_SYMBOL(acpi_unregister_ioapic); +static unsigned long __init +acpi_scan_rsdp(unsigned long start, unsigned long length) +{ + unsigned long offset = 0; + unsigned long sig_len = sizeof("RSD PTR ") - 1; + + /* + * Scan all 16-byte boundaries of the physical memory region for the + * RSDP signature. + */ + for (offset = 0; offset < length; offset += 16) { + if (strncmp((char *)(phys_to_virt(start) + offset), "RSD PTR ", sig_len)) + continue; + return (start + offset); + } + + return 0; +} + static int __init acpi_parse_sbf(struct acpi_table_header *table) { struct acpi_table_boot *sb; @@ -729,6 +748,27 @@ static int __init acpi_parse_fadt(struct acpi_table_header *table) return 0; } +unsigned long __init acpi_find_rsdp(void) +{ + unsigned long rsdp_phys = 0; + + if (efi_enabled) { + if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) + return efi.acpi20; + else if (efi.acpi != EFI_INVALID_TABLE_ADDR) + return efi.acpi; + } + /* + * Scan memory looking for the RSDP signature. First search EBDA (low + * memory) paragraphs and then search upper memory (E0000-FFFFF). + */ + rsdp_phys = acpi_scan_rsdp(0, 0x400); + if (!rsdp_phys) + rsdp_phys = acpi_scan_rsdp(0xE0000, 0x20000); + + return rsdp_phys; +} + #ifdef CONFIG_X86_LOCAL_APIC /* * Parse LAPIC entries in MADT diff --git a/trunk/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c b/trunk/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c index 98d4fdb7dc04..76c3ab0da468 100644 --- a/trunk/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c +++ b/trunk/arch/x86/kernel/cpu/cpufreq/speedstep-lib.c @@ -189,7 +189,10 @@ static unsigned int pentium4_get_frequency(void) printk(KERN_DEBUG "speedstep-lib: couldn't detect FSB speed. Please send an e-mail to \n"); /* Multiplier. */ - mult = msr_lo >> 24; + if (c->x86_model < 2) + mult = msr_lo >> 27; + else + mult = msr_lo >> 24; dprintk("P4 - FSB %u kHz; Multiplier %u; Speed %u kHz\n", fsb, mult, (fsb * mult)); diff --git a/trunk/arch/x86/kernel/srat_32.c b/trunk/arch/x86/kernel/srat_32.c index b72e61359c36..2bf6903cb444 100644 --- a/trunk/arch/x86/kernel/srat_32.c +++ b/trunk/arch/x86/kernel/srat_32.c @@ -274,7 +274,7 @@ int __init get_memcfg_from_srat(void) int tables = 0; int i = 0; - rsdp_address = acpi_os_get_root_pointer(); + rsdp_address = acpi_find_rsdp(); if (!rsdp_address) { printk("%s: System description tables not found\n", __FUNCTION__); diff --git a/trunk/drivers/Kconfig b/trunk/drivers/Kconfig index b86877bdc7ac..d74d9fbb9fd2 100644 --- a/trunk/drivers/Kconfig +++ b/trunk/drivers/Kconfig @@ -60,8 +60,6 @@ source "drivers/power/Kconfig" source "drivers/hwmon/Kconfig" -source "drivers/thermal/Kconfig" - source "drivers/watchdog/Kconfig" source "drivers/ssb/Kconfig" diff --git a/trunk/drivers/Makefile b/trunk/drivers/Makefile index 30ba97ec5eb5..f1c11db52a57 100644 --- a/trunk/drivers/Makefile +++ b/trunk/drivers/Makefile @@ -65,7 +65,6 @@ obj-y += i2c/ obj-$(CONFIG_W1) += w1/ obj-$(CONFIG_POWER_SUPPLY) += power/ obj-$(CONFIG_HWMON) += hwmon/ -obj-$(CONFIG_THERMAL) += thermal/ obj-$(CONFIG_WATCHDOG) += watchdog/ obj-$(CONFIG_PHONE) += telephony/ obj-$(CONFIG_MD) += md/ diff --git a/trunk/drivers/acpi/Kconfig b/trunk/drivers/acpi/Kconfig index 0065f3794576..ccf6ea95f68c 100644 --- a/trunk/drivers/acpi/Kconfig +++ b/trunk/drivers/acpi/Kconfig @@ -186,7 +186,6 @@ config ACPI_HOTPLUG_CPU config ACPI_THERMAL tristate "Thermal Zone" depends on ACPI_PROCESSOR - select THERMAL default y help This driver adds support for ACPI thermal zones. Most mobile and @@ -200,16 +199,6 @@ config ACPI_NUMA depends on (X86 || IA64) default y if IA64_GENERIC || IA64_SGI_SN2 -config ACPI_WMI - tristate "WMI (EXPERIMENTAL)" - depends on EXPERIMENTAL - help - This driver adds support for the ACPI-WMI mapper device (PNP0C14) - found on some systems. - - NOTE: You will need another driver or userspace application on top of - this to actually use anything defined in the ACPI-WMI mapper. - config ACPI_ASUS tristate "ASUS/Medion Laptop Extras" depends on X86 diff --git a/trunk/drivers/acpi/Makefile b/trunk/drivers/acpi/Makefile index f29812a86533..456446f90077 100644 --- a/trunk/drivers/acpi/Makefile +++ b/trunk/drivers/acpi/Makefile @@ -55,7 +55,6 @@ obj-$(CONFIG_ACPI_THERMAL) += thermal.o obj-$(CONFIG_ACPI_SYSTEM) += system.o event.o obj-$(CONFIG_ACPI_DEBUG) += debug.o obj-$(CONFIG_ACPI_NUMA) += numa.o -obj-$(CONFIG_ACPI_WMI) += wmi.o obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o diff --git a/trunk/drivers/acpi/asus_acpi.c b/trunk/drivers/acpi/asus_acpi.c index d25ef961415c..d915fec9bf63 100644 --- a/trunk/drivers/acpi/asus_acpi.c +++ b/trunk/drivers/acpi/asus_acpi.c @@ -142,7 +142,6 @@ struct asus_hotk { xxN, //M2400N, M3700N, M5200N, M6800N, S1300N, S5200N A4S, //Z81sp //(Centrino) - F3Sa, END_MODEL } model; //Models currently supported u16 event_count[128]; //count for each event TODO make this better @@ -406,20 +405,7 @@ static struct model_data model_conf[END_MODEL] = { .brightness_get = "GPLV", .mt_bt_switch = "BLED", .mt_wled = "WLED" - }, - - { - .name = "F3Sa", - .mt_bt_switch = "BLED", - .mt_wled = "WLED", - .mt_mled = "MLED", - .brightness_get = "GPLV", - .brightness_set = "SPLV", - .mt_lcd_switch = "\\_SB.PCI0.SBRG.EC0._Q10", - .lcd_status = "\\_SB.PCI0.SBRG.EC0.RPIN", - .display_get = "\\ADVG", - .display_set = "SDSP", - }, + } }; @@ -724,8 +710,15 @@ static int get_lcd_state(void) { int lcd = 0; - if (hotk->model == L3H) { - /* L3H and the like have to be handled differently */ + if (hotk->model != L3H) { + /* We don't have to check anything if we are here */ + if (!read_acpi_int(NULL, hotk->methods->lcd_status, &lcd)) + printk(KERN_WARNING + "Asus ACPI: Error reading LCD status\n"); + + if (hotk->model == L2D) + lcd = ~lcd; + } else { /* L3H and the like have to be handled differently */ acpi_status status = 0; struct acpi_object_list input; union acpi_object mt_params[2]; @@ -752,32 +745,6 @@ static int get_lcd_state(void) if (out_obj.type == ACPI_TYPE_INTEGER) /* That's what the AML code does */ lcd = out_obj.integer.value >> 8; - } else if (hotk->model == F3Sa) { - unsigned long tmp; - union acpi_object param; - struct acpi_object_list input; - acpi_status status; - - /* Read pin 11 */ - param.type = ACPI_TYPE_INTEGER; - param.integer.value = 0x11; - input.count = 1; - input.pointer = ¶m; - - status = acpi_evaluate_integer(NULL, hotk->methods->lcd_status, - &input, &tmp); - if (status != AE_OK) - return -1; - - lcd = tmp; - } else { - /* We don't have to check anything if we are here */ - if (!read_acpi_int(NULL, hotk->methods->lcd_status, &lcd)) - printk(KERN_WARNING - "Asus ACPI: Error reading LCD status\n"); - - if (hotk->model == L2D) - lcd = ~lcd; } return (lcd & 1); @@ -1167,8 +1134,6 @@ static int asus_model_match(char *model) return W5A; else if (strncmp(model, "A4S", 3) == 0) return A4S; - else if (strncmp(model, "F3Sa", 4) == 0) - return F3Sa; else return END_MODEL; } diff --git a/trunk/drivers/acpi/battery.c b/trunk/drivers/acpi/battery.c index f6215e809808..c4a769d1ba85 100644 --- a/trunk/drivers/acpi/battery.c +++ b/trunk/drivers/acpi/battery.c @@ -194,9 +194,6 @@ static int acpi_battery_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_MANUFACTURER: val->strval = battery->oem_info; break; - case POWER_SUPPLY_PROP_SERIAL_NUMBER: - val->strval = battery->serial_number; - break; default: return -EINVAL; } @@ -215,7 +212,6 @@ static enum power_supply_property charge_battery_props[] = { POWER_SUPPLY_PROP_CHARGE_NOW, POWER_SUPPLY_PROP_MODEL_NAME, POWER_SUPPLY_PROP_MANUFACTURER, - POWER_SUPPLY_PROP_SERIAL_NUMBER, }; static enum power_supply_property energy_battery_props[] = { @@ -230,7 +226,6 @@ static enum power_supply_property energy_battery_props[] = { POWER_SUPPLY_PROP_ENERGY_NOW, POWER_SUPPLY_PROP_MODEL_NAME, POWER_SUPPLY_PROP_MANUFACTURER, - POWER_SUPPLY_PROP_SERIAL_NUMBER, }; #endif diff --git a/trunk/drivers/acpi/bay.c b/trunk/drivers/acpi/bay.c index 477711435b24..6daf6088ac88 100644 --- a/trunk/drivers/acpi/bay.c +++ b/trunk/drivers/acpi/bay.c @@ -46,12 +46,6 @@ MODULE_LICENSE("GPL"); printk(KERN_DEBUG PREFIX "%s: %s\n", prefix, s); } static void bay_notify(acpi_handle handle, u32 event, void *data); -static const struct acpi_device_id bay_device_ids[] = { - {"LNXIOBAY", 0}, - {"", 0}, -}; -MODULE_DEVICE_TABLE(acpi, bay_device_ids); - struct bay { acpi_handle handle; char *name; diff --git a/trunk/drivers/acpi/blacklist.c b/trunk/drivers/acpi/blacklist.c index 6dbaa2d15fe0..8809654d6cc9 100644 --- a/trunk/drivers/acpi/blacklist.c +++ b/trunk/drivers/acpi/blacklist.c @@ -70,6 +70,8 @@ static struct acpi_blacklist_item acpi_blacklist[] __initdata = { /* IBM 600E - _ADR should return 7, but it returns 1 */ {"IBM ", "TP600E ", 0x00000105, ACPI_SIG_DSDT, less_than_or_equal, "Incorrect _ADR", 1}, + {"ASUS\0\0", "P2B-S ", 0, ACPI_SIG_DSDT, all_versions, + "Bogus PCI routing", 1}, {""} }; @@ -206,35 +208,33 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { * Disable OSI(Linux) warnings on all "Acer, inc." * * _OSI(Linux) disables the latest Windows BIOS code: - * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3100"), * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5050"), - * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"), * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5580"), * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 3010"), * _OSI(Linux) effect unknown: * DMI_MATCH(DMI_PRODUCT_NAME, "Ferrari 5000"), */ - /* - * note that dmi_check_system() uses strstr() - * to match sub-strings rather than !strcmp(), - * so "Acer" below matches "Acer, inc." above. - */ + { + .callback = dmi_disable_osi_linux, + .ident = "Acer, inc.", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer, inc."), + }, + }, /* * Disable OSI(Linux) warnings on all "Acer" * * _OSI(Linux) effect unknown: + * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"), * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5610"), * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720Z"), * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 5520"), * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 6460"), * DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 7510"), * DMI_MATCH(DMI_PRODUCT_NAME, "Extensa 5220"), - * - * _OSI(Linux) is a NOP: - * DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5315"), */ { - .callback = dmi_disable_osi_linux, + .callback = dmi_unknown_osi_linux, .ident = "Acer", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Acer"), @@ -242,22 +242,21 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, /* * Disable OSI(Linux) warnings on all "Apple Computer, Inc." - * Disable OSI(Linux) warnings on all "Apple Inc." * * _OSI(Linux) confirmed to be a NOP: * DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"), * DMI_MATCH(DMI_PRODUCT_NAME, "MacBook2,1"), * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro2,2"), - * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,1"), * _OSI(Linux) effect unknown: * DMI_MATCH(DMI_PRODUCT_NAME, "MacPro2,1"), * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro1,1"), + * DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3,1"), */ { .callback = dmi_disable_osi_linux, .ident = "Apple", .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Apple"), + DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."), }, }, /* @@ -295,13 +294,13 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { * DMI_MATCH(DMI_BOARD_NAME, "IFL91"), */ { - .callback = dmi_disable_osi_linux, + .callback = dmi_unknown_osi_linux, .ident = "Compal", .matches = { DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"), }, }, - { /* OSI(Linux) touches USB, unknown side-effect */ + { /* OSI(Linux) touches USB, breaks suspend to disk */ .callback = dmi_disable_osi_linux, .ident = "Dell Dimension 5150", .matches = { @@ -311,7 +310,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, { /* OSI(Linux) is a NOP */ .callback = dmi_disable_osi_linux, - .ident = "Dell i1501", + .ident = "Dell", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 1501"), @@ -319,7 +318,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, { /* OSI(Linux) effect unknown */ .callback = dmi_unknown_osi_linux, - .ident = "Dell Latitude D830", + .ident = "Dell", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "Latitude D830"), @@ -327,7 +326,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, { /* OSI(Linux) effect unknown */ .callback = dmi_unknown_osi_linux, - .ident = "Dell OP GX620", + .ident = "Dell", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex GX620"), @@ -335,23 +334,15 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, { /* OSI(Linux) effect unknown */ .callback = dmi_unknown_osi_linux, - .ident = "Dell PE 1900", + .ident = "Dell", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 1900"), }, }, - { /* OSI(Linux) is a NOP */ - .callback = dmi_disable_osi_linux, - .ident = "Dell PE R200", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge R200"), - }, - }, { /* OSI(Linux) touches USB */ .callback = dmi_disable_osi_linux, - .ident = "Dell PR 390", + .ident = "Dell", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "Precision WorkStation 390"), @@ -367,7 +358,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { }, { /* OSI(Linux) effect unknown */ .callback = dmi_unknown_osi_linux, - .ident = "Dell PE SC440", + .ident = "Dell", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge SC440"), @@ -483,11 +474,6 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { * * _OSI(Linux) confirmed to be a NOP: * DMI_MATCH(DMI_PRODUCT_NAME, "P1-J150B"), - * with DMI_MATCH(DMI_BOARD_NAME, "ROCKY"), - * - * unknown: - * DMI_MATCH(DMI_PRODUCT_NAME, "S1-MDGDG"), - * with DMI_MATCH(DMI_BOARD_NAME, "ROCKY"), */ { .callback = dmi_disable_osi_linux, @@ -530,7 +516,7 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { * DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ11M"), */ { - .callback = dmi_disable_osi_linux, + .callback = dmi_unknown_osi_linux, .ident = "Sony", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), diff --git a/trunk/drivers/acpi/bus.c b/trunk/drivers/acpi/bus.c index 8df325dafe0f..1b4cf984b081 100644 --- a/trunk/drivers/acpi/bus.c +++ b/trunk/drivers/acpi/bus.c @@ -122,31 +122,6 @@ int acpi_bus_get_status(struct acpi_device *device) EXPORT_SYMBOL(acpi_bus_get_status); -void acpi_bus_private_data_handler(acpi_handle handle, - u32 function, void *context) -{ - return; -} -EXPORT_SYMBOL(acpi_bus_private_data_handler); - -int acpi_bus_get_private_data(acpi_handle handle, void **data) -{ - acpi_status status = AE_OK; - - if (!*data) - return -EINVAL; - - status = acpi_get_data(handle, acpi_bus_private_data_handler, data); - if (ACPI_FAILURE(status) || !*data) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No context for object [%p]\n", - handle)); - return -ENODEV; - } - - return 0; -} -EXPORT_SYMBOL(acpi_bus_get_private_data); - /* -------------------------------------------------------------------------- Power Management -------------------------------------------------------------------------- */ diff --git a/trunk/drivers/acpi/debug.c b/trunk/drivers/acpi/debug.c index 6df564f4ca6e..bf513e07b773 100644 --- a/trunk/drivers/acpi/debug.c +++ b/trunk/drivers/acpi/debug.c @@ -130,63 +130,6 @@ static int param_get_debug_level(char *buffer, struct kernel_param *kp) { module_param_call(debug_layer, param_set_uint, param_get_debug_layer, &acpi_dbg_layer, 0644); module_param_call(debug_level, param_set_uint, param_get_debug_level, &acpi_dbg_level, 0644); -static char trace_method_name[6]; -module_param_string(trace_method_name, trace_method_name, 6, 0644); -static unsigned int trace_debug_layer; -module_param(trace_debug_layer, uint, 0644); -static unsigned int trace_debug_level; -module_param(trace_debug_level, uint, 0644); - -static int param_set_trace_state(const char *val, struct kernel_param *kp) -{ - int result = 0; - - if (!strncmp(val, "enable", strlen("enable") - 1)) { - result = acpi_debug_trace(trace_method_name, trace_debug_level, - trace_debug_layer, 0); - if (result) - result = -EBUSY; - goto exit; - } - - if (!strncmp(val, "disable", strlen("disable") - 1)) { - int name = 0; - result = acpi_debug_trace((char *)&name, trace_debug_level, - trace_debug_layer, 0); - if (result) - result = -EBUSY; - goto exit; - } - - if (!strncmp(val, "1", 1)) { - result = acpi_debug_trace(trace_method_name, trace_debug_level, - trace_debug_layer, 1); - if (result) - result = -EBUSY; - goto exit; - } - - result = -EINVAL; -exit: - return result; -} - -static int param_get_trace_state(char *buffer, struct kernel_param *kp) -{ - if (!acpi_gbl_trace_method_name) - return sprintf(buffer, "disable"); - else { - if (acpi_gbl_trace_flags & 1) - return sprintf(buffer, "1"); - else - return sprintf(buffer, "enable"); - } - return 0; -} - -module_param_call(trace_state, param_set_trace_state, param_get_trace_state, - NULL, 0644); - /* -------------------------------------------------------------------------- FS Interface (/proc) -------------------------------------------------------------------------- */ diff --git a/trunk/drivers/acpi/dock.c b/trunk/drivers/acpi/dock.c index b3dec2101e2e..1dabdf4c07b3 100644 --- a/trunk/drivers/acpi/dock.c +++ b/trunk/drivers/acpi/dock.c @@ -51,12 +51,6 @@ static struct atomic_notifier_head dock_notifier_list; static struct platform_device *dock_device; static char dock_device_name[] = "dock"; -static const struct acpi_device_id dock_device_ids[] = { - {"LNXDOCK", 0}, - {"", 0}, -}; -MODULE_DEVICE_TABLE(acpi, dock_device_ids); - struct dock_station { acpi_handle handle; unsigned long last_dock_time; diff --git a/trunk/drivers/acpi/ec.c b/trunk/drivers/acpi/ec.c index 7222a18a0319..987b967c7467 100644 --- a/trunk/drivers/acpi/ec.c +++ b/trunk/drivers/acpi/ec.c @@ -573,7 +573,7 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address, void *handler_context, void *region_context) { struct acpi_ec *ec = handler_context; - int result = 0, i; + int result = 0, i = 0; u8 temp = 0; if ((address > 0xFF) || !value || !handler_context) @@ -585,18 +585,7 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address, if (bits != 8 && acpi_strict) return AE_BAD_PARAMETER; - acpi_ec_burst_enable(ec); - - if (function == ACPI_READ) { - result = acpi_ec_read(ec, address, &temp); - *value = temp; - } else { - temp = 0xff & (*value); - result = acpi_ec_write(ec, address, temp); - } - - for (i = 8; unlikely(bits - i > 0); i += 8) { - ++address; + while (bits - i > 0) { if (function == ACPI_READ) { result = acpi_ec_read(ec, address, &temp); (*value) |= ((acpi_integer)temp) << i; @@ -604,10 +593,10 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address, temp = 0xff & ((*value) >> i); result = acpi_ec_write(ec, address, temp); } + i += 8; + ++address; } - acpi_ec_burst_disable(ec); - switch (result) { case -EINVAL: return AE_BAD_PARAMETER; diff --git a/trunk/drivers/acpi/events/evevent.c b/trunk/drivers/acpi/events/evevent.c index 3048801a37b5..e41287815ea1 100644 --- a/trunk/drivers/acpi/events/evevent.c +++ b/trunk/drivers/acpi/events/evevent.c @@ -259,7 +259,7 @@ u32 acpi_ev_fixed_event_detect(void) enable_bit_mask)) { /* Found an active (signalled) event */ - acpi_os_fixed_event_count(i); + int_status |= acpi_ev_fixed_event_dispatch((u32) i); } } diff --git a/trunk/drivers/acpi/events/evgpe.c b/trunk/drivers/acpi/events/evgpe.c index 0dadd2adc800..e22f4a973c0f 100644 --- a/trunk/drivers/acpi/events/evgpe.c +++ b/trunk/drivers/acpi/events/evgpe.c @@ -270,18 +270,18 @@ acpi_status acpi_ev_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) case ACPI_GPE_TYPE_WAKE_RUN: ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_WAKE_ENABLED); - /* fallthrough */ + /*lint -fallthrough */ case ACPI_GPE_TYPE_RUNTIME: /* Disable the requested runtime GPE */ ACPI_CLEAR_BIT(gpe_event_info->flags, ACPI_GPE_RUN_ENABLED); - - /* fallthrough */ + status = acpi_hw_write_gpe_enable_reg(gpe_event_info); + break; default: - acpi_hw_write_gpe_enable_reg(gpe_event_info); + return_ACPI_STATUS(AE_BAD_PARAMETER); } return_ACPI_STATUS(AE_OK); @@ -501,7 +501,6 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) * an interrupt handler. * ******************************************************************************/ -static void acpi_ev_asynch_enable_gpe(void *context); static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) { @@ -577,30 +576,22 @@ static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context) method_node))); } } - /* Defer enabling of GPE until all notify handlers are done */ - acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_asynch_enable_gpe, - gpe_event_info); - return_VOID; -} -static void acpi_ev_asynch_enable_gpe(void *context) -{ - struct acpi_gpe_event_info *gpe_event_info = context; - acpi_status status; - if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == + if ((local_gpe_event_info.flags & ACPI_GPE_XRUPT_TYPE_MASK) == ACPI_GPE_LEVEL_TRIGGERED) { /* * GPE is level-triggered, we clear the GPE status bit after * handling the event. */ - status = acpi_hw_clear_gpe(gpe_event_info); + status = acpi_hw_clear_gpe(&local_gpe_event_info); if (ACPI_FAILURE(status)) { return_VOID; } } /* Enable this GPE */ - (void)acpi_hw_write_gpe_enable_reg(gpe_event_info); + + (void)acpi_hw_write_gpe_enable_reg(&local_gpe_event_info); return_VOID; } @@ -627,7 +618,7 @@ acpi_ev_gpe_dispatch(struct acpi_gpe_event_info *gpe_event_info, u32 gpe_number) ACPI_FUNCTION_TRACE(ev_gpe_dispatch); - acpi_os_gpe_count(gpe_number); + acpi_gpe_count++; /* * If edge-triggered, clear the GPE status bit now. Note that diff --git a/trunk/drivers/acpi/fan.c b/trunk/drivers/acpi/fan.c index 48cb705b274a..a6e149d692cb 100644 --- a/trunk/drivers/acpi/fan.c +++ b/trunk/drivers/acpi/fan.c @@ -30,7 +30,7 @@ #include #include #include -#include + #include #include @@ -68,55 +68,9 @@ static struct acpi_driver acpi_fan_driver = { }, }; -/* thermal cooling device callbacks */ -static int fan_get_max_state(struct thermal_cooling_device *cdev, char *buf) -{ - /* ACPI fan device only support two states: ON/OFF */ - return sprintf(buf, "1\n"); -} - -static int fan_get_cur_state(struct thermal_cooling_device *cdev, char *buf) -{ - struct acpi_device *device = cdev->devdata; - int state; - int result; - - if (!device) - return -EINVAL; - - result = acpi_bus_get_power(device->handle, &state); - if (result) - return result; - - return sprintf(buf, "%s\n", state == ACPI_STATE_D3 ? "0" : - (state == ACPI_STATE_D0 ? "1" : "unknown")); -} - -static int -fan_set_cur_state(struct thermal_cooling_device *cdev, unsigned int state) -{ - struct acpi_device *device = cdev->devdata; - int result; - - if (!device || (state != 0 && state != 1)) - return -EINVAL; - - result = acpi_bus_set_power(device->handle, - state ? ACPI_STATE_D0 : ACPI_STATE_D3); - - return result; -} - -static struct thermal_cooling_device_ops fan_cooling_ops = { - .get_max_state = fan_get_max_state, - .get_cur_state = fan_get_cur_state, - .set_cur_state = fan_set_cur_state, -}; - /* -------------------------------------------------------------------------- FS Interface (/proc) -------------------------------------------------------------------------- */ -#ifdef CONFIG_ACPI_PROCFS static struct proc_dir_entry *acpi_fan_dir; @@ -217,17 +171,7 @@ static int acpi_fan_remove_fs(struct acpi_device *device) return 0; } -#else -static int acpi_fan_add_fs(struct acpi_device *device) -{ - return 0; -} -static int acpi_fan_remove_fs(struct acpi_device *device) -{ - return 0; -} -#endif /* -------------------------------------------------------------------------- Driver Interface -------------------------------------------------------------------------- */ @@ -235,8 +179,9 @@ static int acpi_fan_remove_fs(struct acpi_device *device) static int acpi_fan_add(struct acpi_device *device) { int result = 0; + struct acpi_fan *fan = NULL; int state = 0; - struct thermal_cooling_device *cdev; + if (!device) return -EINVAL; @@ -254,25 +199,6 @@ static int acpi_fan_add(struct acpi_device *device) acpi_bus_set_power(device->handle, state); device->flags.force_power_state = 0; - cdev = thermal_cooling_device_register("Fan", device, - &fan_cooling_ops); - if (cdev) - printk(KERN_INFO PREFIX - "%s is registered as cooling_device%d\n", - device->dev.bus_id, cdev->id); - else - goto end; - acpi_driver_data(device) = cdev; - result = sysfs_create_link(&device->dev.kobj, &cdev->device.kobj, - "thermal_cooling"); - if (result) - return result; - - result = sysfs_create_link(&cdev->device.kobj, &device->dev.kobj, - "device"); - if (result) - return result; - result = acpi_fan_add_fs(device); if (result) goto end; @@ -282,20 +208,18 @@ static int acpi_fan_add(struct acpi_device *device) !device->power.state ? "on" : "off"); end: + if (result) + kfree(fan); + return result; } static int acpi_fan_remove(struct acpi_device *device, int type) { - struct thermal_cooling_device *cdev = acpi_driver_data(device); - - if (!device || !cdev) + if (!device || !acpi_driver_data(device)) return -EINVAL; acpi_fan_remove_fs(device); - sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); - sysfs_remove_link(&cdev->device.kobj, "device"); - thermal_cooling_device_unregister(cdev); return 0; } @@ -337,12 +261,10 @@ static int __init acpi_fan_init(void) int result = 0; -#ifdef CONFIG_ACPI_PROCFS acpi_fan_dir = proc_mkdir(ACPI_FAN_CLASS, acpi_root_dir); if (!acpi_fan_dir) return -ENODEV; acpi_fan_dir->owner = THIS_MODULE; -#endif result = acpi_bus_register_driver(&acpi_fan_driver); if (result < 0) { diff --git a/trunk/drivers/acpi/hardware/hwsleep.c b/trunk/drivers/acpi/hardware/hwsleep.c index 058d0be5cbe2..fd1c4ba63367 100644 --- a/trunk/drivers/acpi/hardware/hwsleep.c +++ b/trunk/drivers/acpi/hardware/hwsleep.c @@ -286,13 +286,13 @@ acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state) } /* - * 1) Disable/Clear all GPEs * 2) Enable all wakeup GPEs */ status = acpi_hw_disable_all_gpes(); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } + acpi_gbl_system_awake_and_running = FALSE; status = acpi_hw_enable_all_wakeup_gpes(); diff --git a/trunk/drivers/acpi/namespace/nsxfeval.c b/trunk/drivers/acpi/namespace/nsxfeval.c index b92133faf5b7..f39fbc6b9237 100644 --- a/trunk/drivers/acpi/namespace/nsxfeval.c +++ b/trunk/drivers/acpi/namespace/nsxfeval.c @@ -443,7 +443,6 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, struct acpica_device_id hid; struct acpi_compatible_id_list *cid; acpi_native_uint i; - int found; status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { @@ -497,19 +496,16 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, /* Walk the CID list */ - found = 0; for (i = 0; i < cid->count; i++) { if (ACPI_STRNCMP(cid->id[i].value, info->hid, sizeof(struct - acpi_compatible_id)) == + acpi_compatible_id)) != 0) { - found = 1; - break; + ACPI_FREE(cid); + return (AE_OK); } } ACPI_FREE(cid); - if (!found) - return (AE_OK); } } diff --git a/trunk/drivers/acpi/osl.c b/trunk/drivers/acpi/osl.c index 3b8aef3aefe5..e53fb516f9d4 100644 --- a/trunk/drivers/acpi/osl.c +++ b/trunk/drivers/acpi/osl.c @@ -120,7 +120,7 @@ static char osi_additional_string[OSI_STRING_LENGTH_MAX]; */ #define OSI_LINUX_ENABLE 0 -static struct osi_linux { +struct osi_linux { unsigned int enable:1; unsigned int dmi:1; unsigned int cmdline:1; @@ -250,16 +250,11 @@ acpi_physical_address __init acpi_os_get_root_pointer(void) "System description tables not found\n"); return 0; } - } else { - acpi_physical_address pa = 0; - - acpi_find_root_pointer(&pa); - return pa; - } + } else + return acpi_find_rsdp(); } -void __iomem *__init_refok -acpi_os_map_memory(acpi_physical_address phys, acpi_size size) +void __iomem *acpi_os_map_memory(acpi_physical_address phys, acpi_size size) { if (phys > ULONG_MAX) { printk(KERN_ERR PREFIX "Cannot map memory that high\n"); @@ -337,15 +332,7 @@ acpi_os_table_override(struct acpi_table_header * existing_table, static irqreturn_t acpi_irq(int irq, void *dev_id) { - u32 handled; - - handled = (*acpi_irq_handler) (acpi_irq_context); - - if (handled) { - acpi_irq_handled++; - return IRQ_HANDLED; - } else - return IRQ_NONE; + return (*acpi_irq_handler) (acpi_irq_context) ? IRQ_HANDLED : IRQ_NONE; } acpi_status @@ -354,8 +341,6 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, { unsigned int irq; - acpi_irq_stats_init(); - /* * Ignore the GSI from the core, and use the value in our copy of the * FADT. It may not be the same if an interrupt source override exists @@ -676,6 +661,25 @@ static void acpi_os_execute_deferred(struct work_struct *work) dpc->function(dpc->context); kfree(dpc); + /* Yield cpu to notify thread */ + cond_resched(); + + return; +} + +static void acpi_os_execute_notify(struct work_struct *work) +{ + struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); + + if (!dpc) { + printk(KERN_ERR PREFIX "Invalid (NULL) context\n"); + return; + } + + dpc->function(dpc->context); + + kfree(dpc); + return; } @@ -699,7 +703,7 @@ acpi_status acpi_os_execute(acpi_execute_type type, { acpi_status status = AE_OK; struct acpi_os_dpc *dpc; - struct workqueue_struct *queue; + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Scheduling function [%p(%p)] for deferred execution.\n", function, context)); @@ -723,13 +727,20 @@ acpi_status acpi_os_execute(acpi_execute_type type, dpc->function = function; dpc->context = context; - INIT_WORK(&dpc->work, acpi_os_execute_deferred); - queue = (type == OSL_NOTIFY_HANDLER) ? kacpi_notify_wq : kacpid_wq; - if (!queue_work(queue, &dpc->work)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Call to queue_work() failed.\n")); - status = AE_ERROR; - kfree(dpc); + if (type == OSL_NOTIFY_HANDLER) { + INIT_WORK(&dpc->work, acpi_os_execute_notify); + if (!queue_work(kacpi_notify_wq, &dpc->work)) { + status = AE_ERROR; + kfree(dpc); + } + } else { + INIT_WORK(&dpc->work, acpi_os_execute_deferred); + if (!queue_work(kacpid_wq, &dpc->work)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Call to queue_work() failed.\n")); + status = AE_ERROR; + kfree(dpc); + } } return_ACPI_STATUS(status); } @@ -1202,24 +1213,24 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object) * * Returns 0 on success */ -static int acpi_dmi_dump(void) +int acpi_dmi_dump(void) { if (!dmi_available) return -1; printk(KERN_NOTICE PREFIX "DMI System Vendor: %s\n", - dmi_get_system_info(DMI_SYS_VENDOR)); + dmi_get_slot(DMI_SYS_VENDOR)); printk(KERN_NOTICE PREFIX "DMI Product Name: %s\n", - dmi_get_system_info(DMI_PRODUCT_NAME)); + dmi_get_slot(DMI_PRODUCT_NAME)); printk(KERN_NOTICE PREFIX "DMI Product Version: %s\n", - dmi_get_system_info(DMI_PRODUCT_VERSION)); + dmi_get_slot(DMI_PRODUCT_VERSION)); printk(KERN_NOTICE PREFIX "DMI Board Name: %s\n", - dmi_get_system_info(DMI_BOARD_NAME)); + dmi_get_slot(DMI_BOARD_NAME)); printk(KERN_NOTICE PREFIX "DMI BIOS Vendor: %s\n", - dmi_get_system_info(DMI_BIOS_VENDOR)); + dmi_get_slot(DMI_BIOS_VENDOR)); printk(KERN_NOTICE PREFIX "DMI BIOS Date: %s\n", - dmi_get_system_info(DMI_BIOS_DATE)); + dmi_get_slot(DMI_BIOS_DATE)); return 0; } diff --git a/trunk/drivers/acpi/pci_irq.c b/trunk/drivers/acpi/pci_irq.c index 76d9c669d2d8..62010c2481b3 100644 --- a/trunk/drivers/acpi/pci_irq.c +++ b/trunk/drivers/acpi/pci_irq.c @@ -51,8 +51,10 @@ static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(int segment, int bus, int device, int pin) { + struct list_head *node = NULL; struct acpi_prt_entry *entry = NULL; + if (!acpi_prt.count) return NULL; @@ -62,7 +64,8 @@ static struct acpi_prt_entry *acpi_pci_irq_find_prt_entry(int segment, * */ spin_lock(&acpi_prt_lock); - list_for_each_entry(entry, &acpi_prt.entries, node) { + list_for_each(node, &acpi_prt.entries) { + entry = list_entry(node, struct acpi_prt_entry, node); if ((segment == entry->id.segment) && (bus == entry->id.bus) && (device == entry->id.device) diff --git a/trunk/drivers/acpi/power.c b/trunk/drivers/acpi/power.c index 76bf6d90c700..af1769a20c7a 100644 --- a/trunk/drivers/acpi/power.c +++ b/trunk/drivers/acpi/power.c @@ -458,9 +458,11 @@ int acpi_power_transition(struct acpi_device *device, int state) } end: - if (result) + if (result) { device->power.state = ACPI_STATE_UNKNOWN; - else { + printk(KERN_WARNING PREFIX "Transitioning device [%s] to D%d\n", + device->pnp.bus_id, state); + } else { /* We shouldn't change the state till all above operations succeed */ device->power.state = state; } diff --git a/trunk/drivers/acpi/processor_core.c b/trunk/drivers/acpi/processor_core.c index 315fd8f7e8a1..e48ee4f8749f 100644 --- a/trunk/drivers/acpi/processor_core.c +++ b/trunk/drivers/acpi/processor_core.c @@ -668,24 +668,6 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device) acpi_processor_power_init(pr, device); - pr->cdev = thermal_cooling_device_register("Processor", device, - &processor_cooling_ops); - if (pr->cdev) - printk(KERN_INFO PREFIX - "%s is registered as cooling_device%d\n", - device->dev.bus_id, pr->cdev->id); - else - goto end; - - result = sysfs_create_link(&device->dev.kobj, &pr->cdev->device.kobj, - "thermal_cooling"); - if (result) - return result; - result = sysfs_create_link(&pr->cdev->device.kobj, &device->dev.kobj, - "device"); - if (result) - return result; - if (pr->flags.throttling) { printk(KERN_INFO PREFIX "%s [%s] (supports", acpi_device_name(device), acpi_device_bid(device)); @@ -809,11 +791,6 @@ static int acpi_processor_remove(struct acpi_device *device, int type) acpi_processor_remove_fs(device); - sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); - sysfs_remove_link(&pr->cdev->device.kobj, "device"); - thermal_cooling_device_unregister(pr->cdev); - pr->cdev = NULL; - processors[pr->id] = NULL; kfree(pr); @@ -835,18 +812,11 @@ static int is_processor_present(acpi_handle handle) status = acpi_evaluate_integer(handle, "_STA", NULL, &sta); - /* - * if a processor object does not have an _STA object, - * OSPM assumes that the processor is present. - */ - if (status == AE_NOT_FOUND) - return 1; - - if (ACPI_SUCCESS(status) && (sta & ACPI_STA_DEVICE_PRESENT)) - return 1; - - ACPI_EXCEPTION((AE_INFO, status, "Processor Device is not present")); - return 0; + if (ACPI_FAILURE(status) || !(sta & ACPI_STA_DEVICE_PRESENT)) { + ACPI_EXCEPTION((AE_INFO, status, "Processor Device is not present")); + return 0; + } + return 1; } static diff --git a/trunk/drivers/acpi/processor_idle.c b/trunk/drivers/acpi/processor_idle.c index 32003fdc91e8..199ea2146153 100644 --- a/trunk/drivers/acpi/processor_idle.c +++ b/trunk/drivers/acpi/processor_idle.c @@ -98,9 +98,6 @@ module_param(bm_history, uint, 0644); static int acpi_processor_set_power_policy(struct acpi_processor *pr); -#else /* CONFIG_CPU_IDLE */ -static unsigned int latency_factor __read_mostly = 2; -module_param(latency_factor, uint, 0644); #endif /* @@ -204,10 +201,6 @@ static inline u32 ticks_elapsed_in_us(u32 t1, u32 t2) return PM_TIMER_TICKS_TO_US((0xFFFFFFFF - t1) + t2); } -/* - * Callers should disable interrupts before the call and enable - * interrupts after return. - */ static void acpi_safe_halt(void) { current_thread_info()->status &= ~TS_POLLING; @@ -268,7 +261,7 @@ static atomic_t c3_cpu_count; /* Common C-state entry for C2, C3, .. */ static void acpi_cstate_enter(struct acpi_processor_cx *cstate) { - if (cstate->entry_method == ACPI_CSTATE_FFH) { + if (cstate->space_id == ACPI_CSTATE_FFH) { /* Call into architectural FFH based C-state */ acpi_processor_ffh_cstate_enter(cstate); } else { @@ -420,8 +413,6 @@ static void acpi_processor_idle(void) pm_idle_save(); else acpi_safe_halt(); - - local_irq_enable(); return; } @@ -530,7 +521,6 @@ static void acpi_processor_idle(void) * skew otherwise. */ sleep_ticks = 0xFFFFFFFF; - local_irq_enable(); break; case ACPI_STATE_C2: @@ -932,20 +922,20 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) cx.address = reg->address; cx.index = current_count + 1; - cx.entry_method = ACPI_CSTATE_SYSTEMIO; + cx.space_id = ACPI_CSTATE_SYSTEMIO; if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) { if (acpi_processor_ffh_cstate_probe (pr->id, &cx, reg) == 0) { - cx.entry_method = ACPI_CSTATE_FFH; - } else if (cx.type == ACPI_STATE_C1) { + cx.space_id = ACPI_CSTATE_FFH; + } else if (cx.type != ACPI_STATE_C1) { /* * C1 is a special case where FIXED_HARDWARE * can be handled in non-MWAIT way as well. * In that case, save this _CST entry info. + * That is, we retain space_id of SYSTEM_IO for + * halt based C1. * Otherwise, ignore this info and continue. */ - cx.entry_method = ACPI_CSTATE_HALT; - } else { continue; } } @@ -1379,16 +1369,12 @@ static inline void acpi_idle_update_bm_rld(struct acpi_processor *pr, /** * acpi_idle_do_entry - a helper function that does C2 and C3 type entry * @cx: cstate data - * - * Caller disables interrupt before call and enables interrupt after return. */ static inline void acpi_idle_do_entry(struct acpi_processor_cx *cx) { - if (cx->entry_method == ACPI_CSTATE_FFH) { + if (cx->space_id == ACPI_CSTATE_FFH) { /* Call into architectural FFH based C-state */ acpi_processor_ffh_cstate_enter(cx); - } else if (cx->entry_method == ACPI_CSTATE_HALT) { - acpi_safe_halt(); } else { int unused; /* IO port based C-state */ @@ -1410,27 +1396,21 @@ static inline void acpi_idle_do_entry(struct acpi_processor_cx *cx) static int acpi_idle_enter_c1(struct cpuidle_device *dev, struct cpuidle_state *state) { - u32 t1, t2; struct acpi_processor *pr; struct acpi_processor_cx *cx = cpuidle_get_statedata(state); - pr = processors[smp_processor_id()]; if (unlikely(!pr)) return 0; - local_irq_disable(); if (pr->flags.bm_check) acpi_idle_update_bm_rld(pr, cx); - t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); - acpi_idle_do_entry(cx); - t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); + acpi_safe_halt(); - local_irq_enable(); cx->usage++; - return ticks_elapsed_in_us(t1, t2); + return 0; } /** @@ -1537,9 +1517,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, if (dev->safe_state) { return dev->safe_state->enter(dev, dev->safe_state); } else { - local_irq_disable(); acpi_safe_halt(); - local_irq_enable(); return 0; } } @@ -1631,7 +1609,7 @@ struct cpuidle_driver acpi_idle_driver = { */ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) { - int i, count = CPUIDLE_DRIVER_STATE_START; + int i, count = 0; struct acpi_processor_cx *cx; struct cpuidle_state *state; struct cpuidle_device *dev = &pr->power.dev; @@ -1660,14 +1638,13 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i); state->exit_latency = cx->latency; - state->target_residency = cx->latency * latency_factor; + state->target_residency = cx->latency * 6; state->power_usage = cx->power; state->flags = 0; switch (cx->type) { case ACPI_STATE_C1: state->flags |= CPUIDLE_FLAG_SHALLOW; - state->flags |= CPUIDLE_FLAG_TIME_VALID; state->enter = acpi_idle_enter_c1; dev->safe_state = state; break; @@ -1690,8 +1667,6 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) } count++; - if (count == CPUIDLE_STATE_MAX) - break; } dev->state_count = count; diff --git a/trunk/drivers/acpi/processor_perflib.c b/trunk/drivers/acpi/processor_perflib.c index f32010bee4d5..463b0247cbc5 100644 --- a/trunk/drivers/acpi/processor_perflib.c +++ b/trunk/drivers/acpi/processor_perflib.c @@ -60,11 +60,6 @@ static DEFINE_MUTEX(performance_mutex); * policy is adjusted accordingly. */ -static unsigned int ignore_ppc = 0; -module_param(ignore_ppc, uint, 0644); -MODULE_PARM_DESC(ignore_ppc, "If the frequency of your machine gets wrongly" \ - "limited by BIOS, this should help"); - #define PPC_REGISTERED 1 #define PPC_IN_USE 2 @@ -77,9 +72,6 @@ static int acpi_processor_ppc_notifier(struct notifier_block *nb, struct acpi_processor *pr; unsigned int ppc = 0; - if (ignore_ppc) - return 0; - mutex_lock(&performance_mutex); if (event != CPUFREQ_INCOMPATIBLE) @@ -138,13 +130,7 @@ static int acpi_processor_get_platform_limit(struct acpi_processor *pr) int acpi_processor_ppc_has_changed(struct acpi_processor *pr) { - int ret; - - if (ignore_ppc) - return 0; - - ret = acpi_processor_get_platform_limit(pr); - + int ret = acpi_processor_get_platform_limit(pr); if (ret < 0) return (ret); else diff --git a/trunk/drivers/acpi/processor_thermal.c b/trunk/drivers/acpi/processor_thermal.c index 9cb43f52f7b6..06e6f3fb8825 100644 --- a/trunk/drivers/acpi/processor_thermal.c +++ b/trunk/drivers/acpi/processor_thermal.c @@ -32,7 +32,6 @@ #include #include #include -#include #include @@ -94,9 +93,6 @@ static int acpi_processor_apply_limit(struct acpi_processor *pr) * _any_ cpufreq driver and not only the acpi-cpufreq driver. */ -#define CPUFREQ_THERMAL_MIN_STEP 0 -#define CPUFREQ_THERMAL_MAX_STEP 3 - static unsigned int cpufreq_thermal_reduction_pctg[NR_CPUS]; static unsigned int acpi_thermal_cpufreq_is_init = 0; @@ -113,9 +109,8 @@ static int acpi_thermal_cpufreq_increase(unsigned int cpu) if (!cpu_has_cpufreq(cpu)) return -ENODEV; - if (cpufreq_thermal_reduction_pctg[cpu] < - CPUFREQ_THERMAL_MAX_STEP) { - cpufreq_thermal_reduction_pctg[cpu]++; + if (cpufreq_thermal_reduction_pctg[cpu] < 60) { + cpufreq_thermal_reduction_pctg[cpu] += 20; cpufreq_update_policy(cpu); return 0; } @@ -128,9 +123,8 @@ static int acpi_thermal_cpufreq_decrease(unsigned int cpu) if (!cpu_has_cpufreq(cpu)) return -ENODEV; - if (cpufreq_thermal_reduction_pctg[cpu] > - (CPUFREQ_THERMAL_MIN_STEP + 1)) - cpufreq_thermal_reduction_pctg[cpu]--; + if (cpufreq_thermal_reduction_pctg[cpu] > 20) + cpufreq_thermal_reduction_pctg[cpu] -= 20; else cpufreq_thermal_reduction_pctg[cpu] = 0; cpufreq_update_policy(cpu); @@ -149,7 +143,7 @@ static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb, max_freq = (policy->cpuinfo.max_freq * - (100 - cpufreq_thermal_reduction_pctg[policy->cpu] * 20)) / 100; + (100 - cpufreq_thermal_reduction_pctg[policy->cpu])) / 100; cpufreq_verify_within_limits(policy, 0, max_freq); @@ -161,32 +155,6 @@ static struct notifier_block acpi_thermal_cpufreq_notifier_block = { .notifier_call = acpi_thermal_cpufreq_notifier, }; -static int cpufreq_get_max_state(unsigned int cpu) -{ - if (!cpu_has_cpufreq(cpu)) - return 0; - - return CPUFREQ_THERMAL_MAX_STEP; -} - -static int cpufreq_get_cur_state(unsigned int cpu) -{ - if (!cpu_has_cpufreq(cpu)) - return 0; - - return cpufreq_thermal_reduction_pctg[cpu]; -} - -static int cpufreq_set_cur_state(unsigned int cpu, int state) -{ - if (!cpu_has_cpufreq(cpu)) - return 0; - - cpufreq_thermal_reduction_pctg[cpu] = state; - cpufreq_update_policy(cpu); - return 0; -} - void acpi_thermal_cpufreq_init(void) { int i; @@ -211,20 +179,6 @@ void acpi_thermal_cpufreq_exit(void) } #else /* ! CONFIG_CPU_FREQ */ -static int cpufreq_get_max_state(unsigned int cpu) -{ - return 0; -} - -static int cpufreq_get_cur_state(unsigned int cpu) -{ - return 0; -} - -static int cpufreq_set_cur_state(unsigned int cpu, int state) -{ - return 0; -} static int acpi_thermal_cpufreq_increase(unsigned int cpu) { @@ -356,84 +310,6 @@ int acpi_processor_get_limit_info(struct acpi_processor *pr) return 0; } -/* thermal coolign device callbacks */ -static int acpi_processor_max_state(struct acpi_processor *pr) -{ - int max_state = 0; - - /* - * There exists four states according to - * cpufreq_thermal_reduction_ptg. 0, 1, 2, 3 - */ - max_state += cpufreq_get_max_state(pr->id); - if (pr->flags.throttling) - max_state += (pr->throttling.state_count -1); - - return max_state; -} -static int -processor_get_max_state(struct thermal_cooling_device *cdev, char *buf) -{ - struct acpi_device *device = cdev->devdata; - struct acpi_processor *pr = acpi_driver_data(device); - - if (!device || !pr) - return -EINVAL; - - return sprintf(buf, "%d\n", acpi_processor_max_state(pr)); -} - -static int -processor_get_cur_state(struct thermal_cooling_device *cdev, char *buf) -{ - struct acpi_device *device = cdev->devdata; - struct acpi_processor *pr = acpi_driver_data(device); - int cur_state; - - if (!device || !pr) - return -EINVAL; - - cur_state = cpufreq_get_cur_state(pr->id); - if (pr->flags.throttling) - cur_state += pr->throttling.state; - - return sprintf(buf, "%d\n", cur_state); -} - -static int -processor_set_cur_state(struct thermal_cooling_device *cdev, unsigned int state) -{ - struct acpi_device *device = cdev->devdata; - struct acpi_processor *pr = acpi_driver_data(device); - int result = 0; - int max_pstate; - - if (!device || !pr) - return -EINVAL; - - max_pstate = cpufreq_get_max_state(pr->id); - - if (state > acpi_processor_max_state(pr)) - return -EINVAL; - - if (state <= max_pstate) { - if (pr->flags.throttling && pr->throttling.state) - result = acpi_processor_set_throttling(pr, 0); - cpufreq_set_cur_state(pr->id, state); - } else { - cpufreq_set_cur_state(pr->id, max_pstate); - result = acpi_processor_set_throttling(pr, - state - max_pstate); - } - return result; -} - -struct thermal_cooling_device_ops processor_cooling_ops = { - .get_max_state = processor_get_max_state, - .get_cur_state = processor_get_cur_state, - .set_cur_state = processor_set_cur_state, -}; - /* /proc interface */ static int acpi_processor_limit_seq_show(struct seq_file *seq, void *offset) diff --git a/trunk/drivers/acpi/scan.c b/trunk/drivers/acpi/scan.c index c7b0aa52dd23..d9d531cce27f 100644 --- a/trunk/drivers/acpi/scan.c +++ b/trunk/drivers/acpi/scan.c @@ -941,15 +941,6 @@ static int acpi_bay_match(struct acpi_device *device){ return -ENODEV; } -/* - * acpi_dock_match - see if a device has a _DCK method - */ -static int acpi_dock_match(struct acpi_device *device) -{ - acpi_handle tmp; - return acpi_get_handle(device->handle, "_DCK", &tmp); -} - static void acpi_device_set_id(struct acpi_device *device, struct acpi_device *parent, acpi_handle handle, int type) @@ -959,7 +950,6 @@ static void acpi_device_set_id(struct acpi_device *device, char *hid = NULL; char *uid = NULL; struct acpi_compatible_id_list *cid_list = NULL; - const char *cid_add = NULL; acpi_status status; switch (type) { @@ -982,18 +972,15 @@ static void acpi_device_set_id(struct acpi_device *device, device->flags.bus_address = 1; } - /* If we have a video/bay/dock device, add our selfdefined - HID to the CID list. Like that the video/bay/dock drivers - will get autoloaded and the device might still match - against another driver. - */ - if (ACPI_SUCCESS(acpi_video_bus_match(device))) - cid_add = ACPI_VIDEO_HID; - else if (ACPI_SUCCESS(acpi_bay_match(device))) - cid_add = ACPI_BAY_HID; - else if (ACPI_SUCCESS(acpi_dock_match(device))) - cid_add = ACPI_DOCK_HID; + if(!(info->valid & (ACPI_VALID_HID | ACPI_VALID_CID))){ + status = acpi_video_bus_match(device); + if(ACPI_SUCCESS(status)) + hid = ACPI_VIDEO_HID; + status = acpi_bay_match(device); + if (ACPI_SUCCESS(status)) + hid = ACPI_BAY_HID; + } break; case ACPI_BUS_TYPE_POWER: hid = ACPI_POWER_HID; @@ -1034,44 +1021,11 @@ static void acpi_device_set_id(struct acpi_device *device, strcpy(device->pnp.unique_id, uid); device->flags.unique_id = 1; } - if (cid_list || cid_add) { - struct acpi_compatible_id_list *list; - int size = 0; - int count = 0; - - if (cid_list) { - size = cid_list->size; - } else if (cid_add) { - size = sizeof(struct acpi_compatible_id_list); - cid_list = ACPI_ALLOCATE_ZEROED((acpi_size) size); - if (!cid_list) { - printk(KERN_ERR "Memory allocation error\n"); - kfree(buffer.pointer); - return; - } else { - cid_list->count = 0; - cid_list->size = size; - } - } - if (cid_add) - size += sizeof(struct acpi_compatible_id); - list = kmalloc(size, GFP_KERNEL); - - if (list) { - if (cid_list) { - memcpy(list, cid_list, cid_list->size); - count = cid_list->count; - } - if (cid_add) { - strncpy(list->id[count].value, cid_add, - ACPI_MAX_CID_LENGTH); - count++; - device->flags.compatible_ids = 1; - } - list->size = size; - list->count = count; - device->pnp.cid_list = list; - } else + if (cid_list) { + device->pnp.cid_list = kmalloc(cid_list->size, GFP_KERNEL); + if (device->pnp.cid_list) + memcpy(device->pnp.cid_list, cid_list, cid_list->size); + else printk(KERN_ERR "Memory allocation error\n"); } @@ -1126,20 +1080,6 @@ static int acpi_bus_remove(struct acpi_device *dev, int rmdevice) return 0; } -static int -acpi_is_child_device(struct acpi_device *device, - int (*matcher)(struct acpi_device *)) -{ - int result = -ENODEV; - - do { - if (ACPI_SUCCESS(matcher(device))) - return AE_OK; - } while ((device = device->parent)); - - return result; -} - static int acpi_add_single_object(struct acpi_device **child, struct acpi_device *parent, acpi_handle handle, int type, @@ -1191,20 +1131,10 @@ acpi_add_single_object(struct acpi_device **child, case ACPI_BUS_TYPE_PROCESSOR: case ACPI_BUS_TYPE_DEVICE: result = acpi_bus_get_status(device); - if (ACPI_FAILURE(result)) { - result = -ENODEV; + if (ACPI_FAILURE(result) || !device->status.present) { + result = -ENOENT; goto end; } - if (!device->status.present) { - /* Bay and dock should be handled even if absent */ - if (!ACPI_SUCCESS( - acpi_is_child_device(device, acpi_bay_match)) && - !ACPI_SUCCESS( - acpi_is_child_device(device, acpi_dock_match))) { - result = -ENODEV; - goto end; - } - } break; default: STRUCT_TO_INT(device->status) = diff --git a/trunk/drivers/acpi/sleep/main.c b/trunk/drivers/acpi/sleep/main.c index 293a1cbb47c0..485de1347075 100644 --- a/trunk/drivers/acpi/sleep/main.c +++ b/trunk/drivers/acpi/sleep/main.c @@ -170,7 +170,7 @@ static int acpi_pm_enter(suspend_state_t pm_state) /* Reprogram control registers and execute _BFS */ acpi_leave_sleep_state_prep(acpi_state); - /* ACPI 3.0 specs (P62) says that it's the responsibility + /* ACPI 3.0 specs (P62) says that it's the responsabilty * of the OSPM to clear the status bit [ implying that the * POWER_BUTTON event should not reach userspace ] */ @@ -472,20 +472,11 @@ int acpi_pm_device_sleep_state(struct device *dev, int wake, int *d_min_p) if (acpi_target_sleep_state == ACPI_STATE_S0 || (wake && adev->wakeup.state.enabled && adev->wakeup.sleep_state <= acpi_target_sleep_state)) { - acpi_status status; - acpi_method[3] = 'W'; - status = acpi_evaluate_integer(handle, acpi_method, NULL, - &d_max); - if (ACPI_FAILURE(status)) { - d_max = d_min; - } else if (d_max < d_min) { - /* Warn the user of the broken DSDT */ - printk(KERN_WARNING "ACPI: Wrong value from %s\n", - acpi_method); - /* Sanitize it */ + acpi_evaluate_integer(handle, acpi_method, NULL, &d_max); + /* Sanity check */ + if (d_max < d_min) d_min = d_max; - } } if (d_min_p) diff --git a/trunk/drivers/acpi/sleep/proc.c b/trunk/drivers/acpi/sleep/proc.c index f8df5217d477..1538355c266b 100644 --- a/trunk/drivers/acpi/sleep/proc.c +++ b/trunk/drivers/acpi/sleep/proc.c @@ -178,9 +178,6 @@ static int get_date_field(char **p, u32 * value) * Try to find delimeter, only to insert null. The end of the * string won't have one, but is still valid. */ - if (*p == NULL) - return result; - next = strpbrk(*p, "- :"); if (next) *next++ = '\0'; @@ -193,8 +190,6 @@ static int get_date_field(char **p, u32 * value) if (next) *p = next; - else - *p = NULL; return result; } @@ -256,6 +251,27 @@ acpi_system_write_alarm(struct file *file, if ((result = get_date_field(&p, &sec))) goto end; + if (sec > 59) { + min += 1; + sec -= 60; + } + if (min > 59) { + hr += 1; + min -= 60; + } + if (hr > 23) { + day += 1; + hr -= 24; + } + if (day > 31) { + mo += 1; + day -= 31; + } + if (mo > 12) { + yr += 1; + mo -= 12; + } + spin_lock_irq(&rtc_lock); rtc_control = CMOS_READ(RTC_CONTROL); @@ -272,24 +288,24 @@ acpi_system_write_alarm(struct file *file, spin_unlock_irq(&rtc_lock); if (sec > 59) { - min += sec/60; - sec = sec%60; + min++; + sec -= 60; } if (min > 59) { - hr += min/60; - min = min%60; + hr++; + min -= 60; } if (hr > 23) { - day += hr/24; - hr = hr%24; + day++; + hr -= 24; } if (day > 31) { - mo += day/32; - day = day%32; + mo++; + day -= 31; } if (mo > 12) { - yr += mo/13; - mo = mo%13; + yr++; + mo -= 12; } spin_lock_irq(&rtc_lock); diff --git a/trunk/drivers/acpi/system.c b/trunk/drivers/acpi/system.c index ce881713f7a6..5ffe0ea18967 100644 --- a/trunk/drivers/acpi/system.c +++ b/trunk/drivers/acpi/system.c @@ -40,8 +40,6 @@ ACPI_MODULE_NAME("system"); #define ACPI_SYSTEM_CLASS "system" #define ACPI_SYSTEM_DEVICE_NAME "System" -u32 acpi_irq_handled; - /* * Make ACPICA version work as module param */ @@ -168,212 +166,6 @@ static int acpi_system_sysfs_init(void) return 0; } -/* - * Detailed ACPI IRQ counters in /sys/firmware/acpi/interrupts/ - * See Documentation/ABI/testing/sysfs-firmware-acpi - */ - -#define COUNT_GPE 0 -#define COUNT_SCI 1 /* acpi_irq_handled */ -#define COUNT_ERROR 2 /* other */ -#define NUM_COUNTERS_EXTRA 3 - -static u32 *all_counters; -static u32 num_gpes; -static u32 num_counters; -static struct attribute **all_attrs; -static u32 acpi_gpe_count; - -static struct attribute_group interrupt_stats_attr_group = { - .name = "interrupts", -}; -static struct kobj_attribute *counter_attrs; - -static int count_num_gpes(void) -{ - int count = 0; - struct acpi_gpe_xrupt_info *gpe_xrupt_info; - struct acpi_gpe_block_info *gpe_block; - acpi_cpu_flags flags; - - flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); - - gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head; - while (gpe_xrupt_info) { - gpe_block = gpe_xrupt_info->gpe_block_list_head; - while (gpe_block) { - count += gpe_block->register_count * - ACPI_GPE_REGISTER_WIDTH; - gpe_block = gpe_block->next; - } - gpe_xrupt_info = gpe_xrupt_info->next; - } - acpi_os_release_lock(acpi_gbl_gpe_lock, flags); - - return count; -} - -static void delete_gpe_attr_array(void) -{ - u32 *tmp = all_counters; - - all_counters = NULL; - kfree(tmp); - - if (counter_attrs) { - int i; - - for (i = 0; i < num_gpes; i++) - kfree(counter_attrs[i].attr.name); - - kfree(counter_attrs); - } - kfree(all_attrs); - - return; -} - -void acpi_os_gpe_count(u32 gpe_number) -{ - acpi_gpe_count++; - - if (!all_counters) - return; - - if (gpe_number < num_gpes) - all_counters[gpe_number]++; - else - all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR]++; - - return; -} - -void acpi_os_fixed_event_count(u32 event_number) -{ - if (!all_counters) - return; - - if (event_number < ACPI_NUM_FIXED_EVENTS) - all_counters[num_gpes + event_number]++; - else - all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR]++; - - return; -} - -static ssize_t counter_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf) -{ - all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI] = - acpi_irq_handled; - all_counters[num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE] = - acpi_gpe_count; - - return sprintf(buf, "%d\n", all_counters[attr - counter_attrs]); -} - -/* - * counter_set() sets the specified counter. - * setting the total "sci" file to any value clears all counters. - */ -static ssize_t counter_set(struct kobject *kobj, - struct kobj_attribute *attr, const char *buf, size_t size) -{ - int index = attr - counter_attrs; - - if (index == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI) { - int i; - for (i = 0; i < num_counters; ++i) - all_counters[i] = 0; - acpi_gpe_count = 0; - acpi_irq_handled = 0; - - } else - all_counters[index] = strtoul(buf, NULL, 0); - - return size; -} - -void acpi_irq_stats_init(void) -{ - int i; - - if (all_counters) - return; - - num_gpes = count_num_gpes(); - num_counters = num_gpes + ACPI_NUM_FIXED_EVENTS + NUM_COUNTERS_EXTRA; - - all_attrs = kzalloc(sizeof(struct attribute *) * (num_counters + 1), - GFP_KERNEL); - if (all_attrs == NULL) - return; - - all_counters = kzalloc(sizeof(u32) * (num_counters), GFP_KERNEL); - if (all_counters == NULL) - goto fail; - - counter_attrs = kzalloc(sizeof(struct kobj_attribute) * (num_counters), - GFP_KERNEL); - if (counter_attrs == NULL) - goto fail; - - for (i = 0; i < num_counters; ++i) { - char buffer[10]; - char *name; - - if (i < num_gpes) - sprintf(buffer, "gpe%02X", i); - else if (i == num_gpes + ACPI_EVENT_PMTIMER) - sprintf(buffer, "ff_pmtimer"); - else if (i == num_gpes + ACPI_EVENT_GLOBAL) - sprintf(buffer, "ff_gbl_lock"); - else if (i == num_gpes + ACPI_EVENT_POWER_BUTTON) - sprintf(buffer, "ff_pwr_btn"); - else if (i == num_gpes + ACPI_EVENT_SLEEP_BUTTON) - sprintf(buffer, "ff_slp_btn"); - else if (i == num_gpes + ACPI_EVENT_RTC) - sprintf(buffer, "ff_rt_clk"); - else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_GPE) - sprintf(buffer, "gpe_all"); - else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_SCI) - sprintf(buffer, "sci"); - else if (i == num_gpes + ACPI_NUM_FIXED_EVENTS + COUNT_ERROR) - sprintf(buffer, "error"); - else - sprintf(buffer, "bug%02X", i); - - name = kzalloc(strlen(buffer) + 1, GFP_KERNEL); - if (name == NULL) - goto fail; - strncpy(name, buffer, strlen(buffer) + 1); - - counter_attrs[i].attr.name = name; - counter_attrs[i].attr.mode = 0644; - counter_attrs[i].show = counter_show; - counter_attrs[i].store = counter_set; - - all_attrs[i] = &counter_attrs[i].attr; - } - - interrupt_stats_attr_group.attrs = all_attrs; - sysfs_create_group(acpi_kobj, &interrupt_stats_attr_group); - return; - -fail: - delete_gpe_attr_array(); - return; -} - -static void __exit interrupt_stats_exit(void) -{ - sysfs_remove_group(acpi_kobj, &interrupt_stats_attr_group); - - delete_gpe_attr_array(); - - return; -} - /* -------------------------------------------------------------------------- FS Interface (/proc) -------------------------------------------------------------------------- */ diff --git a/trunk/drivers/acpi/tables/Makefile b/trunk/drivers/acpi/tables/Makefile index 7385efa61622..0a7d7afac255 100644 --- a/trunk/drivers/acpi/tables/Makefile +++ b/trunk/drivers/acpi/tables/Makefile @@ -2,6 +2,6 @@ # Makefile for all Linux ACPI interpreter subdirectories # -obj-y := tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o tbxfroot.o +obj-y := tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o EXTRA_CFLAGS += $(ACPI_CFLAGS) diff --git a/trunk/drivers/acpi/tables/tbxfroot.c b/trunk/drivers/acpi/tables/tbxfroot.c index 9ecb4b6c1e7d..cf8fa514189f 100644 --- a/trunk/drivers/acpi/tables/tbxfroot.c +++ b/trunk/drivers/acpi/tables/tbxfroot.c @@ -100,7 +100,7 @@ static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp) /******************************************************************************* * - * FUNCTION: acpi_find_root_pointer + * FUNCTION: acpi_tb_find_rsdp * * PARAMETERS: table_address - Where the table pointer is returned * @@ -219,6 +219,8 @@ acpi_status acpi_find_root_pointer(acpi_native_uint * table_address) return_ACPI_STATUS(AE_NOT_FOUND); } +ACPI_EXPORT_SYMBOL(acpi_find_root_pointer) + /******************************************************************************* * * FUNCTION: acpi_tb_scan_memory_for_rsdp diff --git a/trunk/drivers/acpi/thermal.c b/trunk/drivers/acpi/thermal.c index 8d4b79b4f933..5f79b4451212 100644 --- a/trunk/drivers/acpi/thermal.c +++ b/trunk/drivers/acpi/thermal.c @@ -43,7 +43,7 @@ #include #include #include -#include + #include #include @@ -65,6 +65,9 @@ #define ACPI_THERMAL_MAX_ACTIVE 10 #define ACPI_THERMAL_MAX_LIMIT_STR_LEN 65 +#define KELVIN_TO_CELSIUS(t) (long)(((long)t-2732>=0) ? ((long)t-2732+5)/10 : ((long)t-2732-5)/10) +#define CELSIUS_TO_KELVIN(t) ((t+273)*10) + #define _COMPONENT ACPI_THERMAL_COMPONENT ACPI_MODULE_NAME("thermal"); @@ -192,8 +195,6 @@ struct acpi_thermal { struct acpi_thermal_trips trips; struct acpi_handle_list devices; struct timer_list timer; - struct thermal_zone_device *thermal_zone; - int tz_enabled; struct mutex lock; }; @@ -320,226 +321,178 @@ static int acpi_thermal_set_cooling_mode(struct acpi_thermal *tz, int mode) return 0; } -#define ACPI_TRIPS_CRITICAL 0x01 -#define ACPI_TRIPS_HOT 0x02 -#define ACPI_TRIPS_PASSIVE 0x04 -#define ACPI_TRIPS_ACTIVE 0x08 -#define ACPI_TRIPS_DEVICES 0x10 - -#define ACPI_TRIPS_REFRESH_THRESHOLDS (ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE) -#define ACPI_TRIPS_REFRESH_DEVICES ACPI_TRIPS_DEVICES - -#define ACPI_TRIPS_INIT (ACPI_TRIPS_CRITICAL | ACPI_TRIPS_HOT | \ - ACPI_TRIPS_PASSIVE | ACPI_TRIPS_ACTIVE | \ - ACPI_TRIPS_DEVICES) - -/* - * This exception is thrown out in two cases: - * 1.An invalid trip point becomes invalid or a valid trip point becomes invalid - * when re-evaluating the AML code. - * 2.TODO: Devices listed in _PSL, _ALx, _TZD may change. - * We need to re-bind the cooling devices of a thermal zone when this occurs. - */ -#define ACPI_THERMAL_TRIPS_EXCEPTION(flags, str) \ -do { \ - if (flags != ACPI_TRIPS_INIT) \ - ACPI_EXCEPTION((AE_INFO, AE_ERROR, \ - "ACPI thermal trip point %s changed\n" \ - "Please send acpidump to linux-acpi@vger.kernel.org\n", str)); \ -} while (0) - -static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) +static int acpi_thermal_get_trip_points(struct acpi_thermal *tz) { acpi_status status = AE_OK; - struct acpi_handle_list devices; - int valid = 0; - int i; + int i = 0; + + + if (!tz) + return -EINVAL; /* Critical Shutdown (required) */ - if (flag & ACPI_TRIPS_CRITICAL) { - status = acpi_evaluate_integer(tz->device->handle, - "_CRT", NULL, &tz->trips.critical.temperature); - if (ACPI_FAILURE(status)) { + + status = acpi_evaluate_integer(tz->device->handle, "_CRT", NULL, + &tz->trips.critical.temperature); + if (ACPI_FAILURE(status)) { + tz->trips.critical.flags.valid = 0; + ACPI_EXCEPTION((AE_INFO, status, "No critical threshold")); + return -ENODEV; + } else { + tz->trips.critical.flags.valid = 1; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Found critical threshold [%lu]\n", + tz->trips.critical.temperature)); + } + + if (tz->trips.critical.flags.valid == 1) { + if (crt == -1) { tz->trips.critical.flags.valid = 0; - ACPI_EXCEPTION((AE_INFO, status, - "No critical threshold")); - return -ENODEV; - } else { - tz->trips.critical.flags.valid = 1; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Found critical threshold [%lu]\n", - tz->trips.critical.temperature)); - } - if (tz->trips.critical.flags.valid == 1) { - if (crt == -1) { - tz->trips.critical.flags.valid = 0; - } else if (crt > 0) { - unsigned long crt_k = CELSIUS_TO_KELVIN(crt); - /* - * Allow override to lower critical threshold - */ - if (crt_k < tz->trips.critical.temperature) - tz->trips.critical.temperature = crt_k; - } + } else if (crt > 0) { + unsigned long crt_k = CELSIUS_TO_KELVIN(crt); + + /* + * Allow override to lower critical threshold + */ + if (crt_k < tz->trips.critical.temperature) + tz->trips.critical.temperature = crt_k; } } /* Critical Sleep (optional) */ - if (flag & ACPI_TRIPS_HOT) { + + status = + acpi_evaluate_integer(tz->device->handle, "_HOT", NULL, + &tz->trips.hot.temperature); + if (ACPI_FAILURE(status)) { + tz->trips.hot.flags.valid = 0; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No hot threshold\n")); + } else { + tz->trips.hot.flags.valid = 1; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found hot threshold [%lu]\n", + tz->trips.hot.temperature)); + } + + /* Passive: Processors (optional) */ + + if (psv == -1) { + status = AE_SUPPORT; + } else if (psv > 0) { + tz->trips.passive.temperature = CELSIUS_TO_KELVIN(psv); + status = AE_OK; + } else { status = acpi_evaluate_integer(tz->device->handle, - "_HOT", NULL, &tz->trips.hot.temperature); - if (ACPI_FAILURE(status)) { - tz->trips.hot.flags.valid = 0; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "No hot threshold\n")); - } else { - tz->trips.hot.flags.valid = 1; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Found hot threshold [%lu]\n", - tz->trips.critical.temperature)); - } + "_PSV", NULL, &tz->trips.passive.temperature); } - /* Passive (optional) */ - if (flag & ACPI_TRIPS_PASSIVE) { - valid = tz->trips.passive.flags.valid; - if (psv == -1) { - status = AE_SUPPORT; - } else if (psv > 0) { - tz->trips.passive.temperature = CELSIUS_TO_KELVIN(psv); - status = AE_OK; - } else { - status = acpi_evaluate_integer(tz->device->handle, - "_PSV", NULL, &tz->trips.passive.temperature); - } + if (ACPI_FAILURE(status)) { + tz->trips.passive.flags.valid = 0; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No passive threshold\n")); + } else { + tz->trips.passive.flags.valid = 1; + status = + acpi_evaluate_integer(tz->device->handle, "_TC1", NULL, + &tz->trips.passive.tc1); if (ACPI_FAILURE(status)) tz->trips.passive.flags.valid = 0; - else { - tz->trips.passive.flags.valid = 1; - if (flag == ACPI_TRIPS_INIT) { - status = acpi_evaluate_integer( - tz->device->handle, "_TC1", - NULL, &tz->trips.passive.tc1); - if (ACPI_FAILURE(status)) - tz->trips.passive.flags.valid = 0; - status = acpi_evaluate_integer( - tz->device->handle, "_TC2", - NULL, &tz->trips.passive.tc2); - if (ACPI_FAILURE(status)) - tz->trips.passive.flags.valid = 0; - status = acpi_evaluate_integer( - tz->device->handle, "_TSP", - NULL, &tz->trips.passive.tsp); - if (ACPI_FAILURE(status)) - tz->trips.passive.flags.valid = 0; - } - } - } - if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.passive.flags.valid) { - memset(&devices, 0, sizeof(struct acpi_handle_list)); - status = acpi_evaluate_reference(tz->device->handle, "_PSL", - NULL, &devices); + + status = + acpi_evaluate_integer(tz->device->handle, "_TC2", NULL, + &tz->trips.passive.tc2); if (ACPI_FAILURE(status)) tz->trips.passive.flags.valid = 0; - else - tz->trips.passive.flags.valid = 1; - if (memcmp(&tz->trips.passive.devices, &devices, - sizeof(struct acpi_handle_list))) { - memcpy(&tz->trips.passive.devices, &devices, - sizeof(struct acpi_handle_list)); - ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device"); - } - } - if ((flag & ACPI_TRIPS_PASSIVE) || (flag & ACPI_TRIPS_DEVICES)) { - if (valid != tz->trips.passive.flags.valid) - ACPI_THERMAL_TRIPS_EXCEPTION(flag, "state"); + status = + acpi_evaluate_integer(tz->device->handle, "_TSP", NULL, + &tz->trips.passive.tsp); + if (ACPI_FAILURE(status)) + tz->trips.passive.flags.valid = 0; + + status = + acpi_evaluate_reference(tz->device->handle, "_PSL", NULL, + &tz->trips.passive.devices); + if (ACPI_FAILURE(status)) + tz->trips.passive.flags.valid = 0; + + if (!tz->trips.passive.flags.valid) + printk(KERN_WARNING PREFIX "Invalid passive threshold\n"); + else + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Found passive threshold [%lu]\n", + tz->trips.passive.temperature)); } - /* Active (optional) */ + /* Active: Fans, etc. (optional) */ + for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { + char name[5] = { '_', 'A', 'C', ('0' + i), '\0' }; - valid = tz->trips.active[i].flags.valid; if (act == -1) - break; /* disable all active trip points */ - - if (flag & ACPI_TRIPS_ACTIVE) { - status = acpi_evaluate_integer(tz->device->handle, - name, NULL, &tz->trips.active[i].temperature); - if (ACPI_FAILURE(status)) { - tz->trips.active[i].flags.valid = 0; - if (i == 0) - break; - if (act <= 0) - break; - if (i == 1) - tz->trips.active[0].temperature = - CELSIUS_TO_KELVIN(act); - else - /* - * Don't allow override higher than - * the next higher trip point - */ - tz->trips.active[i - 1].temperature = - (tz->trips.active[i - 2].temperature < - CELSIUS_TO_KELVIN(act) ? - tz->trips.active[i - 2].temperature : - CELSIUS_TO_KELVIN(act)); - break; - } else - tz->trips.active[i].flags.valid = 1; - } + break; /* disable all active trip points */ - name[2] = 'L'; - if ((flag & ACPI_TRIPS_DEVICES) && tz->trips.active[i].flags.valid ) { - memset(&devices, 0, sizeof(struct acpi_handle_list)); - status = acpi_evaluate_reference(tz->device->handle, - name, NULL, &devices); - if (ACPI_FAILURE(status)) - tz->trips.active[i].flags.valid = 0; - else - tz->trips.active[i].flags.valid = 1; - - if (memcmp(&tz->trips.active[i].devices, &devices, - sizeof(struct acpi_handle_list))) { - memcpy(&tz->trips.active[i].devices, &devices, - sizeof(struct acpi_handle_list)); - ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device"); - } - } - if ((flag & ACPI_TRIPS_ACTIVE) || (flag & ACPI_TRIPS_DEVICES)) - if (valid != tz->trips.active[i].flags.valid) - ACPI_THERMAL_TRIPS_EXCEPTION(flag, "state"); + status = acpi_evaluate_integer(tz->device->handle, + name, NULL, &tz->trips.active[i].temperature); - if (!tz->trips.active[i].flags.valid) + if (ACPI_FAILURE(status)) { + if (i == 0) /* no active trip points */ + break; + if (act <= 0) /* no override requested */ + break; + if (i == 1) { /* 1 trip point */ + tz->trips.active[0].temperature = + CELSIUS_TO_KELVIN(act); + } else { /* multiple trips */ + /* + * Don't allow override higher than + * the next higher trip point + */ + tz->trips.active[i - 1].temperature = + (tz->trips.active[i - 2].temperature < + CELSIUS_TO_KELVIN(act) ? + tz->trips.active[i - 2].temperature : + CELSIUS_TO_KELVIN(act)); + } break; - } - - if (flag & ACPI_TRIPS_DEVICES) { - memset(&devices, 0, sizeof(struct acpi_handle_list)); - status = acpi_evaluate_reference(tz->device->handle, "_TZD", - NULL, &devices); - if (memcmp(&tz->devices, &devices, - sizeof(struct acpi_handle_list))) { - memcpy(&tz->devices, &devices, - sizeof(struct acpi_handle_list)); - ACPI_THERMAL_TRIPS_EXCEPTION(flag, "device"); } + + name[2] = 'L'; + status = + acpi_evaluate_reference(tz->device->handle, name, NULL, + &tz->trips.active[i].devices); + if (ACPI_SUCCESS(status)) { + tz->trips.active[i].flags.valid = 1; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Found active threshold [%d]:[%lu]\n", + i, tz->trips.active[i].temperature)); + } else + ACPI_EXCEPTION((AE_INFO, status, + "Invalid active threshold [%d]", i)); } return 0; } -static int acpi_thermal_get_trip_points(struct acpi_thermal *tz) +static int acpi_thermal_get_devices(struct acpi_thermal *tz) { - return acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT); + acpi_status status = AE_OK; + + + if (!tz) + return -EINVAL; + + status = + acpi_evaluate_reference(tz->device->handle, "_TZD", NULL, &tz->devices); + if (ACPI_FAILURE(status)) + return -ENODEV; + + return 0; } static int acpi_thermal_critical(struct acpi_thermal *tz) { - if (!tz || !tz->trips.critical.flags.valid) + if (!tz || !tz->trips.critical.flags.valid || nocrt) return -EINVAL; if (tz->temperature >= tz->trips.critical.temperature) { @@ -548,6 +501,9 @@ static int acpi_thermal_critical(struct acpi_thermal *tz) } else if (tz->trips.critical.flags.enabled) tz->trips.critical.flags.enabled = 0; + printk(KERN_EMERG + "Critical temperature reached (%ld C), shutting down.\n", + KELVIN_TO_CELSIUS(tz->temperature)); acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_CRITICAL, tz->trips.critical.flags.enabled); acpi_bus_generate_netlink_event(tz->device->pnp.device_class, @@ -555,20 +511,14 @@ static int acpi_thermal_critical(struct acpi_thermal *tz) ACPI_THERMAL_NOTIFY_CRITICAL, tz->trips.critical.flags.enabled); - /* take no action if nocrt is set */ - if(!nocrt) { - printk(KERN_EMERG - "Critical temperature reached (%ld C), shutting down.\n", - KELVIN_TO_CELSIUS(tz->temperature)); - orderly_poweroff(true); - } + orderly_poweroff(true); return 0; } static int acpi_thermal_hot(struct acpi_thermal *tz) { - if (!tz || !tz->trips.hot.flags.valid) + if (!tz || !tz->trips.hot.flags.valid || nocrt) return -EINVAL; if (tz->temperature >= tz->trips.hot.temperature) { @@ -584,7 +534,7 @@ static int acpi_thermal_hot(struct acpi_thermal *tz) ACPI_THERMAL_NOTIFY_HOT, tz->trips.hot.flags.enabled); - /* TBD: Call user-mode "sleep(S4)" function if nocrt is cleared */ + /* TBD: Call user-mode "sleep(S4)" function */ return 0; } @@ -782,9 +732,6 @@ static void acpi_thermal_check(void *data) if (result) goto unlock; - if (!tz->tz_enabled) - goto unlock; - memset(&tz->state, 0, sizeof(tz->state)); /* @@ -878,290 +825,6 @@ static void acpi_thermal_check(void *data) mutex_unlock(&tz->lock); } -/* sys I/F for generic thermal sysfs support */ -static int thermal_get_temp(struct thermal_zone_device *thermal, char *buf) -{ - struct acpi_thermal *tz = thermal->devdata; - - if (!tz) - return -EINVAL; - - return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS(tz->temperature)); -} - -static const char enabled[] = "kernel"; -static const char disabled[] = "user"; -static int thermal_get_mode(struct thermal_zone_device *thermal, - char *buf) -{ - struct acpi_thermal *tz = thermal->devdata; - - if (!tz) - return -EINVAL; - - return sprintf(buf, "%s\n", tz->tz_enabled ? - enabled : disabled); -} - -static int thermal_set_mode(struct thermal_zone_device *thermal, - const char *buf) -{ - struct acpi_thermal *tz = thermal->devdata; - int enable; - - if (!tz) - return -EINVAL; - - /* - * enable/disable thermal management from ACPI thermal driver - */ - if (!strncmp(buf, enabled, sizeof enabled - 1)) - enable = 1; - else if (!strncmp(buf, disabled, sizeof disabled - 1)) - enable = 0; - else - return -EINVAL; - - if (enable != tz->tz_enabled) { - tz->tz_enabled = enable; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "%s ACPI thermal control\n", - tz->tz_enabled ? enabled : disabled)); - acpi_thermal_check(tz); - } - return 0; -} - -static int thermal_get_trip_type(struct thermal_zone_device *thermal, - int trip, char *buf) -{ - struct acpi_thermal *tz = thermal->devdata; - int i; - - if (!tz || trip < 0) - return -EINVAL; - - if (tz->trips.critical.flags.valid) { - if (!trip) - return sprintf(buf, "critical\n"); - trip--; - } - - if (tz->trips.hot.flags.valid) { - if (!trip) - return sprintf(buf, "hot\n"); - trip--; - } - - if (tz->trips.passive.flags.valid) { - if (!trip) - return sprintf(buf, "passive\n"); - trip--; - } - - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && - tz->trips.active[i].flags.valid; i++) { - if (!trip) - return sprintf(buf, "active%d\n", i); - trip--; - } - - return -EINVAL; -} - -static int thermal_get_trip_temp(struct thermal_zone_device *thermal, - int trip, char *buf) -{ - struct acpi_thermal *tz = thermal->devdata; - int i; - - if (!tz || trip < 0) - return -EINVAL; - - if (tz->trips.critical.flags.valid) { - if (!trip) - return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS( - tz->trips.critical.temperature)); - trip--; - } - - if (tz->trips.hot.flags.valid) { - if (!trip) - return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS( - tz->trips.hot.temperature)); - trip--; - } - - if (tz->trips.passive.flags.valid) { - if (!trip) - return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS( - tz->trips.passive.temperature)); - trip--; - } - - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && - tz->trips.active[i].flags.valid; i++) { - if (!trip) - return sprintf(buf, "%ld\n", KELVIN_TO_CELSIUS( - tz->trips.active[i].temperature)); - trip--; - } - - return -EINVAL; -} - -typedef int (*cb)(struct thermal_zone_device *, int, - struct thermal_cooling_device *); -static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, - struct thermal_cooling_device *cdev, - cb action) -{ - struct acpi_device *device = cdev->devdata; - struct acpi_thermal *tz = thermal->devdata; - struct acpi_device *dev; - acpi_status status; - acpi_handle handle; - int i; - int j; - int trip = -1; - int result = 0; - - if (tz->trips.critical.flags.valid) - trip++; - - if (tz->trips.hot.flags.valid) - trip++; - - if (tz->trips.passive.flags.valid) { - trip++; - for (i = 0; i < tz->trips.passive.devices.count; - i++) { - handle = tz->trips.passive.devices.handles[i]; - status = acpi_bus_get_device(handle, &dev); - if (ACPI_SUCCESS(status) && (dev == device)) { - result = action(thermal, trip, cdev); - if (result) - goto failed; - } - } - } - - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) { - if (!tz->trips.active[i].flags.valid) - break; - trip++; - for (j = 0; - j < tz->trips.active[i].devices.count; - j++) { - handle = tz->trips.active[i].devices.handles[j]; - status = acpi_bus_get_device(handle, &dev); - if (ACPI_SUCCESS(status) && (dev == device)) { - result = action(thermal, trip, cdev); - if (result) - goto failed; - } - } - } - - for (i = 0; i < tz->devices.count; i++) { - handle = tz->devices.handles[i]; - status = acpi_bus_get_device(handle, &dev); - if (ACPI_SUCCESS(status) && (dev == device)) { - result = action(thermal, -1, cdev); - if (result) - goto failed; - } - } - -failed: - return result; -} - -static int -acpi_thermal_bind_cooling_device(struct thermal_zone_device *thermal, - struct thermal_cooling_device *cdev) -{ - return acpi_thermal_cooling_device_cb(thermal, cdev, - thermal_zone_bind_cooling_device); -} - -static int -acpi_thermal_unbind_cooling_device(struct thermal_zone_device *thermal, - struct thermal_cooling_device *cdev) -{ - return acpi_thermal_cooling_device_cb(thermal, cdev, - thermal_zone_unbind_cooling_device); -} - -static struct thermal_zone_device_ops acpi_thermal_zone_ops = { - .bind = acpi_thermal_bind_cooling_device, - .unbind = acpi_thermal_unbind_cooling_device, - .get_temp = thermal_get_temp, - .get_mode = thermal_get_mode, - .set_mode = thermal_set_mode, - .get_trip_type = thermal_get_trip_type, - .get_trip_temp = thermal_get_trip_temp, -}; - -static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) -{ - int trips = 0; - int result; - acpi_status status; - int i; - - if (tz->trips.critical.flags.valid) - trips++; - - if (tz->trips.hot.flags.valid) - trips++; - - if (tz->trips.passive.flags.valid) - trips++; - - for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && - tz->trips.active[i].flags.valid; i++, trips++); - tz->thermal_zone = thermal_zone_device_register("ACPI thermal zone", - trips, tz, &acpi_thermal_zone_ops); - if (!tz->thermal_zone) - return -ENODEV; - - result = sysfs_create_link(&tz->device->dev.kobj, - &tz->thermal_zone->device.kobj, "thermal_zone"); - if (result) - return result; - - result = sysfs_create_link(&tz->thermal_zone->device.kobj, - &tz->device->dev.kobj, "device"); - if (result) - return result; - - status = acpi_attach_data(tz->device->handle, - acpi_bus_private_data_handler, - tz->thermal_zone); - if (ACPI_FAILURE(status)) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, - "Error attaching device data\n")); - return -ENODEV; - } - - tz->tz_enabled = 1; - - printk(KERN_INFO PREFIX "%s is registered as thermal_zone%d\n", - tz->device->dev.bus_id, tz->thermal_zone->id); - return 0; -} - -static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz) -{ - sysfs_remove_link(&tz->device->dev.kobj, "thermal_zone"); - sysfs_remove_link(&tz->thermal_zone->device.kobj, "device"); - thermal_zone_device_unregister(tz->thermal_zone); - tz->thermal_zone = NULL; - acpi_detach_data(tz->device->handle, acpi_bus_private_data_handler); -} - - /* -------------------------------------------------------------------------- FS Interface (/proc) -------------------------------------------------------------------------- */ @@ -1518,15 +1181,15 @@ static void acpi_thermal_notify(acpi_handle handle, u32 event, void *data) acpi_thermal_check(tz); break; case ACPI_THERMAL_NOTIFY_THRESHOLDS: - acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_THRESHOLDS); + acpi_thermal_get_trip_points(tz); acpi_thermal_check(tz); acpi_bus_generate_proc_event(device, event, 0); acpi_bus_generate_netlink_event(device->pnp.device_class, device->dev.bus_id, event, 0); break; case ACPI_THERMAL_NOTIFY_DEVICES: - acpi_thermal_trips_update(tz, ACPI_TRIPS_REFRESH_DEVICES); - acpi_thermal_check(tz); + if (tz->flags.devices) + acpi_thermal_get_devices(tz); acpi_bus_generate_proc_event(device, event, 0); acpi_bus_generate_netlink_event(device->pnp.device_class, device->dev.bus_id, event, 0); @@ -1569,6 +1232,11 @@ static int acpi_thermal_get_info(struct acpi_thermal *tz) else acpi_thermal_get_polling_frequency(tz); + /* Get devices in this thermal zone [_TZD] (optional) */ + result = acpi_thermal_get_devices(tz); + if (!result) + tz->flags.devices = 1; + return 0; } @@ -1592,19 +1260,13 @@ static int acpi_thermal_add(struct acpi_device *device) strcpy(acpi_device_class(device), ACPI_THERMAL_CLASS); acpi_driver_data(device) = tz; mutex_init(&tz->lock); - - result = acpi_thermal_get_info(tz); if (result) - goto free_memory; - - result = acpi_thermal_register_thermal_zone(tz); - if (result) - goto free_memory; + goto end; result = acpi_thermal_add_fs(device); if (result) - goto unregister_thermal_zone; + goto end; init_timer(&tz->timer); @@ -1615,21 +1277,19 @@ static int acpi_thermal_add(struct acpi_device *device) acpi_thermal_notify, tz); if (ACPI_FAILURE(status)) { result = -ENODEV; - goto remove_fs; + goto end; } printk(KERN_INFO PREFIX "%s [%s] (%ld C)\n", acpi_device_name(device), acpi_device_bid(device), KELVIN_TO_CELSIUS(tz->temperature)); - goto end; -remove_fs: - acpi_thermal_remove_fs(device); -unregister_thermal_zone: - thermal_zone_device_unregister(tz->thermal_zone); -free_memory: - kfree(tz); -end: + end: + if (result) { + acpi_thermal_remove_fs(device); + kfree(tz); + } + return result; } @@ -1669,7 +1329,6 @@ static int acpi_thermal_remove(struct acpi_device *device, int type) } acpi_thermal_remove_fs(device); - acpi_thermal_unregister_thermal_zone(tz); mutex_destroy(&tz->lock); kfree(tz); return 0; diff --git a/trunk/drivers/acpi/utilities/utglobal.c b/trunk/drivers/acpi/utilities/utglobal.c index 630c9a2c5b7b..93ea8290b4f7 100644 --- a/trunk/drivers/acpi/utilities/utglobal.c +++ b/trunk/drivers/acpi/utilities/utglobal.c @@ -671,6 +671,7 @@ void acpi_ut_init_globals(void) /* GPE support */ + acpi_gpe_count = 0; acpi_gbl_gpe_xrupt_list_head = NULL; acpi_gbl_gpe_fadt_blocks[0] = NULL; acpi_gbl_gpe_fadt_blocks[1] = NULL; @@ -734,3 +735,4 @@ void acpi_ut_init_globals(void) ACPI_EXPORT_SYMBOL(acpi_dbg_level) ACPI_EXPORT_SYMBOL(acpi_dbg_layer) + ACPI_EXPORT_SYMBOL(acpi_gpe_count) diff --git a/trunk/drivers/acpi/video.c b/trunk/drivers/acpi/video.c index 82815cff15a9..b1a56bf682ae 100644 --- a/trunk/drivers/acpi/video.c +++ b/trunk/drivers/acpi/video.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include @@ -73,6 +72,9 @@ MODULE_AUTHOR("Bruno Ducrot"); MODULE_DESCRIPTION("ACPI Video Driver"); MODULE_LICENSE("GPL"); +static int brightness_switch_enabled = 1; +module_param(brightness_switch_enabled, bool, 0644); + static int acpi_video_bus_add(struct acpi_device *device); static int acpi_video_bus_remove(struct acpi_device *device, int type); @@ -180,7 +182,6 @@ struct acpi_video_device { struct acpi_device *dev; struct acpi_video_device_brightness *brightness; struct backlight_device *backlight; - struct thermal_cooling_device *cdev; struct output_device *output_dev; }; @@ -294,26 +295,18 @@ static int acpi_video_device_set_state(struct acpi_video_device *device, int sta static int acpi_video_get_brightness(struct backlight_device *bd) { unsigned long cur_level; - int i; struct acpi_video_device *vd = (struct acpi_video_device *)bl_get_data(bd); acpi_video_device_lcd_get_level_current(vd, &cur_level); - for (i = 2; i < vd->brightness->count; i++) { - if (vd->brightness->levels[i] == cur_level) - /* The first two entries are special - see page 575 - of the ACPI spec 3.0 */ - return i-2; - } - return 0; + return (int) cur_level; } static int acpi_video_set_brightness(struct backlight_device *bd) { - int request_level = bd->props.brightness+2; + int request_level = bd->props.brightness; struct acpi_video_device *vd = (struct acpi_video_device *)bl_get_data(bd); - acpi_video_device_lcd_set_level(vd, - vd->brightness->levels[request_level]); + acpi_video_device_lcd_set_level(vd, request_level); return 0; } @@ -344,54 +337,6 @@ static struct output_properties acpi_output_properties = { .set_state = acpi_video_output_set, .get_status = acpi_video_output_get, }; - - -/* thermal cooling device callbacks */ -static int video_get_max_state(struct thermal_cooling_device *cdev, char *buf) -{ - struct acpi_device *device = cdev->devdata; - struct acpi_video_device *video = acpi_driver_data(device); - - return sprintf(buf, "%d\n", video->brightness->count - 3); -} - -static int video_get_cur_state(struct thermal_cooling_device *cdev, char *buf) -{ - struct acpi_device *device = cdev->devdata; - struct acpi_video_device *video = acpi_driver_data(device); - unsigned long level; - int state; - - acpi_video_device_lcd_get_level_current(video, &level); - for (state = 2; state < video->brightness->count; state++) - if (level == video->brightness->levels[state]) - return sprintf(buf, "%d\n", - video->brightness->count - state - 1); - - return -EINVAL; -} - -static int -video_set_cur_state(struct thermal_cooling_device *cdev, unsigned int state) -{ - struct acpi_device *device = cdev->devdata; - struct acpi_video_device *video = acpi_driver_data(device); - int level; - - if ( state >= video->brightness->count - 2) - return -EINVAL; - - state = video->brightness->count - state; - level = video->brightness->levels[state -1]; - return acpi_video_device_lcd_set_level(video, level); -} - -static struct thermal_cooling_device_ops video_cooling_ops = { - .get_max_state = video_get_max_state, - .get_cur_state = video_get_cur_state, - .set_cur_state = video_set_cur_state, -}; - /* -------------------------------------------------------------------------- Video Management -------------------------------------------------------------------------- */ @@ -710,7 +655,7 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) kfree(obj); if (device->cap._BCL && device->cap._BCM && device->cap._BQC && max_level > 0){ - int result; + unsigned long tmp; static int count = 0; char *name; name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); @@ -718,30 +663,14 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) return; sprintf(name, "acpi_video%d", count++); + acpi_video_device_lcd_get_level_current(device, &tmp); device->backlight = backlight_device_register(name, NULL, device, &acpi_backlight_ops); - device->backlight->props.max_brightness = device->brightness->count-3; - device->backlight->props.brightness = acpi_video_get_brightness(device->backlight); + device->backlight->props.max_brightness = max_level; + device->backlight->props.brightness = (int)tmp; backlight_update_status(device->backlight); - kfree(name); - device->cdev = thermal_cooling_device_register("LCD", - device->dev, &video_cooling_ops); - if (device->cdev) { - printk(KERN_INFO PREFIX - "%s is registered as cooling_device%d\n", - device->dev->dev.bus_id, device->cdev->id); - result = sysfs_create_link(&device->dev->dev.kobj, - &device->cdev->device.kobj, - "thermal_cooling"); - if (result) - printk(KERN_ERR PREFIX "Create sysfs link\n"); - result = sysfs_create_link(&device->cdev->device.kobj, - &device->dev->dev.kobj, - "device"); - if (result) - printk(KERN_ERR PREFIX "Create sysfs link\n"); - } + kfree(name); } if (device->cap._DCS && device->cap._DSS){ static int count = 0; @@ -1330,37 +1259,8 @@ acpi_video_bus_write_DOS(struct file *file, static int acpi_video_bus_add_fs(struct acpi_device *device) { - long device_id; - int status; struct proc_dir_entry *entry = NULL; struct acpi_video_bus *video; - struct device *dev; - - status = - acpi_evaluate_integer(device->handle, "_ADR", NULL, &device_id); - - if (!ACPI_SUCCESS(status)) - return -ENODEV; - - /* We need to attempt to determine whether the _ADR refers to a - PCI device or not. There's no terribly good way to do this, - so the best we can hope for is to assume that there'll never - be a video device in the host bridge */ - if (device_id >= 0x10000) { - /* It looks like a PCI device. Does it exist? */ - dev = acpi_get_physical_device(device->handle); - } else { - /* It doesn't look like a PCI device. Does its parent - exist? */ - acpi_handle phandle; - if (acpi_get_parent(device->handle, &phandle)) - return -ENODEV; - dev = acpi_get_physical_device(phandle); - } - if (!dev) - return -ENODEV; - put_device(dev); - video = acpi_driver_data(device); @@ -1832,14 +1732,6 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device) ACPI_DEVICE_NOTIFY, acpi_video_device_notify); backlight_device_unregister(device->backlight); - if (device->cdev) { - sysfs_remove_link(&device->dev->dev.kobj, - "thermal_cooling"); - sysfs_remove_link(&device->cdev->device.kobj, - "device"); - thermal_cooling_device_unregister(device->cdev); - device->cdev = NULL; - } video_output_unregister(device->output_dev); return 0; @@ -1961,27 +1853,32 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) switch (event) { case ACPI_VIDEO_NOTIFY_CYCLE_BRIGHTNESS: /* Cycle brightness */ - acpi_video_switch_brightness(video_device, event); + if (brightness_switch_enabled) + acpi_video_switch_brightness(video_device, event); acpi_bus_generate_proc_event(device, event, 0); keycode = KEY_BRIGHTNESS_CYCLE; break; case ACPI_VIDEO_NOTIFY_INC_BRIGHTNESS: /* Increase brightness */ - acpi_video_switch_brightness(video_device, event); + if (brightness_switch_enabled) + acpi_video_switch_brightness(video_device, event); acpi_bus_generate_proc_event(device, event, 0); keycode = KEY_BRIGHTNESSUP; break; case ACPI_VIDEO_NOTIFY_DEC_BRIGHTNESS: /* Decrease brightness */ - acpi_video_switch_brightness(video_device, event); + if (brightness_switch_enabled) + acpi_video_switch_brightness(video_device, event); acpi_bus_generate_proc_event(device, event, 0); keycode = KEY_BRIGHTNESSDOWN; break; case ACPI_VIDEO_NOTIFY_ZERO_BRIGHTNESS: /* zero brightnesss */ - acpi_video_switch_brightness(video_device, event); + if (brightness_switch_enabled) + acpi_video_switch_brightness(video_device, event); acpi_bus_generate_proc_event(device, event, 0); keycode = KEY_BRIGHTNESS_ZERO; break; case ACPI_VIDEO_NOTIFY_DISPLAY_OFF: /* display device off */ - acpi_video_switch_brightness(video_device, event); + if (brightness_switch_enabled) + acpi_video_switch_brightness(video_device, event); acpi_bus_generate_proc_event(device, event, 0); keycode = KEY_DISPLAY_OFF; break; diff --git a/trunk/drivers/acpi/wmi.c b/trunk/drivers/acpi/wmi.c deleted file mode 100644 index 36b84ab418dd..000000000000 --- a/trunk/drivers/acpi/wmi.c +++ /dev/null @@ -1,710 +0,0 @@ -/* - * ACPI-WMI mapping driver - * - * Copyright (C) 2007-2008 Carlos Corbacho - * - * GUID parsing code from ldm.c is: - * Copyright (C) 2001,2002 Richard Russon - * Copyright (c) 2001-2007 Anton Altaparmakov - * Copyright (C) 2001,2002 Jakob Kemi - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include -#include -#include -#include -#include -#include -#include - -ACPI_MODULE_NAME("wmi"); -MODULE_AUTHOR("Carlos Corbacho"); -MODULE_DESCRIPTION("ACPI-WMI Mapping Driver"); -MODULE_LICENSE("GPL"); - -#define ACPI_WMI_CLASS "wmi" - -#undef PREFIX -#define PREFIX "ACPI: WMI: " - -static DEFINE_MUTEX(wmi_data_lock); - -struct guid_block { - char guid[16]; - union { - char object_id[2]; - struct { - unsigned char notify_id; - unsigned char reserved; - }; - }; - u8 instance_count; - u8 flags; -}; - -struct wmi_block { - struct list_head list; - struct guid_block gblock; - acpi_handle handle; - wmi_notify_handler handler; - void *handler_data; -}; - -static struct wmi_block wmi_blocks; - -/* - * If the GUID data block is marked as expensive, we must enable and - * explicitily disable data collection. - */ -#define ACPI_WMI_EXPENSIVE 0x1 -#define ACPI_WMI_METHOD 0x2 /* GUID is a method */ -#define ACPI_WMI_STRING 0x4 /* GUID takes & returns a string */ -#define ACPI_WMI_EVENT 0x8 /* GUID is an event */ - -static int acpi_wmi_remove(struct acpi_device *device, int type); -static int acpi_wmi_add(struct acpi_device *device); - -static const struct acpi_device_id wmi_device_ids[] = { - {"PNP0C14", 0}, - {"pnp0c14", 0}, - {"", 0}, -}; -MODULE_DEVICE_TABLE(acpi, wmi_device_ids); - -static struct acpi_driver acpi_wmi_driver = { - .name = "wmi", - .class = ACPI_WMI_CLASS, - .ids = wmi_device_ids, - .ops = { - .add = acpi_wmi_add, - .remove = acpi_wmi_remove, - }, -}; - -/* - * GUID parsing functions - */ - -/** - * wmi_parse_hexbyte - Convert a ASCII hex number to a byte - * @src: Pointer to at least 2 characters to convert. - * - * Convert a two character ASCII hex string to a number. - * - * Return: 0-255 Success, the byte was parsed correctly - * -1 Error, an invalid character was supplied - */ -static int wmi_parse_hexbyte(const u8 *src) -{ - unsigned int x; /* For correct wrapping */ - int h; - - /* high part */ - x = src[0]; - if (x - '0' <= '9' - '0') { - h = x - '0'; - } else if (x - 'a' <= 'f' - 'a') { - h = x - 'a' + 10; - } else if (x - 'A' <= 'F' - 'A') { - h = x - 'A' + 10; - } else { - return -1; - } - h <<= 4; - - /* low part */ - x = src[1]; - if (x - '0' <= '9' - '0') - return h | (x - '0'); - if (x - 'a' <= 'f' - 'a') - return h | (x - 'a' + 10); - if (x - 'A' <= 'F' - 'A') - return h | (x - 'A' + 10); - return -1; -} - -/** - * wmi_swap_bytes - Rearrange GUID bytes to match GUID binary - * @src: Memory block holding binary GUID (16 bytes) - * @dest: Memory block to hold byte swapped binary GUID (16 bytes) - * - * Byte swap a binary GUID to match it's real GUID value - */ -static void wmi_swap_bytes(u8 *src, u8 *dest) -{ - int i; - - for (i = 0; i <= 3; i++) - memcpy(dest + i, src + (3 - i), 1); - - for (i = 0; i <= 1; i++) - memcpy(dest + 4 + i, src + (5 - i), 1); - - for (i = 0; i <= 1; i++) - memcpy(dest + 6 + i, src + (7 - i), 1); - - memcpy(dest + 8, src + 8, 8); -} - -/** - * wmi_parse_guid - Convert GUID from ASCII to binary - * @src: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba - * @dest: Memory block to hold binary GUID (16 bytes) - * - * N.B. The GUID need not be NULL terminated. - * - * Return: 'true' @dest contains binary GUID - * 'false' @dest contents are undefined - */ -static bool wmi_parse_guid(const u8 *src, u8 *dest) -{ - static const int size[] = { 4, 2, 2, 2, 6 }; - int i, j, v; - - if (src[8] != '-' || src[13] != '-' || - src[18] != '-' || src[23] != '-') - return false; - - for (j = 0; j < 5; j++, src++) { - for (i = 0; i < size[j]; i++, src += 2, *dest++ = v) { - v = wmi_parse_hexbyte(src); - if (v < 0) - return false; - } - } - - return true; -} - -static bool find_guid(const char *guid_string, struct wmi_block **out) -{ - char tmp[16], guid_input[16]; - struct wmi_block *wblock; - struct guid_block *block; - struct list_head *p; - - wmi_parse_guid(guid_string, tmp); - wmi_swap_bytes(tmp, guid_input); - - list_for_each(p, &wmi_blocks.list) { - wblock = list_entry(p, struct wmi_block, list); - block = &wblock->gblock; - - if (memcmp(block->guid, guid_input, 16) == 0) { - if (out) - *out = wblock; - return 1; - } - } - return 0; -} - -/* - * Exported WMI functions - */ -/** - * wmi_evaluate_method - Evaluate a WMI method - * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba - * @instance: Instance index - * @method_id: Method ID to call - * &in: Buffer containing input for the method call - * &out: Empty buffer to return the method results - * - * Call an ACPI-WMI method - */ -acpi_status wmi_evaluate_method(const char *guid_string, u8 instance, -u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out) -{ - struct guid_block *block = NULL; - struct wmi_block *wblock = NULL; - acpi_handle handle; - acpi_status status; - struct acpi_object_list input; - union acpi_object params[3]; - char method[4] = "WM"; - - if (!find_guid(guid_string, &wblock)) - return AE_BAD_ADDRESS; - - block = &wblock->gblock; - handle = wblock->handle; - - if (!block->flags & ACPI_WMI_METHOD) - return AE_BAD_DATA; - - if (block->instance_count < instance) - return AE_BAD_PARAMETER; - - input.count = 2; - input.pointer = params; - params[0].type = ACPI_TYPE_INTEGER; - params[0].integer.value = instance; - params[1].type = ACPI_TYPE_INTEGER; - params[1].integer.value = method_id; - - if (in) { - input.count = 3; - - if (block->flags & ACPI_WMI_STRING) { - params[2].type = ACPI_TYPE_STRING; - } else { - params[2].type = ACPI_TYPE_BUFFER; - } - params[2].buffer.length = in->length; - params[2].buffer.pointer = in->pointer; - } - - strncat(method, block->object_id, 2); - - status = acpi_evaluate_object(handle, method, &input, out); - - return status; -} -EXPORT_SYMBOL_GPL(wmi_evaluate_method); - -/** - * wmi_query_block - Return contents of a WMI block - * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba - * @instance: Instance index - * &out: Empty buffer to return the contents of the data block to - * - * Return the contents of an ACPI-WMI data block to a buffer - */ -acpi_status wmi_query_block(const char *guid_string, u8 instance, -struct acpi_buffer *out) -{ - struct guid_block *block = NULL; - struct wmi_block *wblock = NULL; - acpi_handle handle; - acpi_status status, wc_status = AE_ERROR; - struct acpi_object_list input, wc_input; - union acpi_object wc_params[1], wq_params[1]; - char method[4]; - char wc_method[4] = "WC"; - - if (!guid_string || !out) - return AE_BAD_PARAMETER; - - if (!find_guid(guid_string, &wblock)) - return AE_BAD_ADDRESS; - - block = &wblock->gblock; - handle = wblock->handle; - - if (block->instance_count < instance) - return AE_BAD_PARAMETER; - - /* Check GUID is a data block */ - if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD)) - return AE_BAD_ADDRESS; - - input.count = 1; - input.pointer = wq_params; - wq_params[0].type = ACPI_TYPE_INTEGER; - wq_params[0].integer.value = instance; - - /* - * If ACPI_WMI_EXPENSIVE, call the relevant WCxx method first to - * enable collection. - */ - if (block->flags & ACPI_WMI_EXPENSIVE) { - wc_input.count = 1; - wc_input.pointer = wc_params; - wc_params[0].type = ACPI_TYPE_INTEGER; - wc_params[0].integer.value = 1; - - strncat(wc_method, block->object_id, 2); - - /* - * Some GUIDs break the specification by declaring themselves - * expensive, but have no corresponding WCxx method. So we - * should not fail if this happens. - */ - wc_status = acpi_evaluate_object(handle, wc_method, - &wc_input, NULL); - } - - strcpy(method, "WQ"); - strncat(method, block->object_id, 2); - - status = acpi_evaluate_object(handle, method, NULL, out); - - /* - * If ACPI_WMI_EXPENSIVE, call the relevant WCxx method, even if - * the WQxx method failed - we should disable collection anyway. - */ - if ((block->flags & ACPI_WMI_EXPENSIVE) && wc_status) { - wc_params[0].integer.value = 0; - status = acpi_evaluate_object(handle, - wc_method, &wc_input, NULL); - } - - return status; -} -EXPORT_SYMBOL_GPL(wmi_query_block); - -/** - * wmi_set_block - Write to a WMI block - * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba - * @instance: Instance index - * &in: Buffer containing new values for the data block - * - * Write the contents of the input buffer to an ACPI-WMI data block - */ -acpi_status wmi_set_block(const char *guid_string, u8 instance, -const struct acpi_buffer *in) -{ - struct guid_block *block = NULL; - struct wmi_block *wblock = NULL; - acpi_handle handle; - struct acpi_object_list input; - union acpi_object params[2]; - char method[4] = "WS"; - - if (!guid_string || !in) - return AE_BAD_DATA; - - if (!find_guid(guid_string, &wblock)) - return AE_BAD_ADDRESS; - - block = &wblock->gblock; - handle = wblock->handle; - - if (block->instance_count < instance) - return AE_BAD_PARAMETER; - - /* Check GUID is a data block */ - if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD)) - return AE_BAD_ADDRESS; - - input.count = 2; - input.pointer = params; - params[0].type = ACPI_TYPE_INTEGER; - params[0].integer.value = instance; - - if (block->flags & ACPI_WMI_STRING) { - params[1].type = ACPI_TYPE_STRING; - } else { - params[1].type = ACPI_TYPE_BUFFER; - } - params[1].buffer.length = in->length; - params[1].buffer.pointer = in->pointer; - - strncat(method, block->object_id, 2); - - return acpi_evaluate_object(handle, method, &input, NULL); -} -EXPORT_SYMBOL_GPL(wmi_set_block); - -/** - * wmi_install_notify_handler - Register handler for WMI events - * @handler: Function to handle notifications - * @data: Data to be returned to handler when event is fired - * - * Register a handler for events sent to the ACPI-WMI mapper device. - */ -acpi_status wmi_install_notify_handler(const char *guid, -wmi_notify_handler handler, void *data) -{ - struct wmi_block *block; - - if (!guid || !handler) - return AE_BAD_PARAMETER; - - find_guid(guid, &block); - if (!block) - return AE_NOT_EXIST; - - if (block->handler) - return AE_ALREADY_ACQUIRED; - - block->handler = handler; - block->handler_data = data; - - return AE_OK; -} -EXPORT_SYMBOL_GPL(wmi_install_notify_handler); - -/** - * wmi_uninstall_notify_handler - Unregister handler for WMI events - * - * Unregister handler for events sent to the ACPI-WMI mapper device. - */ -acpi_status wmi_remove_notify_handler(const char *guid) -{ - struct wmi_block *block; - - if (!guid) - return AE_BAD_PARAMETER; - - find_guid(guid, &block); - if (!block) - return AE_NOT_EXIST; - - if (!block->handler) - return AE_NULL_ENTRY; - - block->handler = NULL; - block->handler_data = NULL; - - return AE_OK; -} -EXPORT_SYMBOL_GPL(wmi_remove_notify_handler); - -/** - * wmi_get_event_data - Get WMI data associated with an event - * - * @event - Event to find - * &out - Buffer to hold event data - * - * Returns extra data associated with an event in WMI. - */ -acpi_status wmi_get_event_data(u32 event, struct acpi_buffer *out) -{ - struct acpi_object_list input; - union acpi_object params[1]; - struct guid_block *gblock; - struct wmi_block *wblock; - struct list_head *p; - - input.count = 1; - input.pointer = params; - params[0].type = ACPI_TYPE_INTEGER; - params[0].integer.value = event; - - list_for_each(p, &wmi_blocks.list) { - wblock = list_entry(p, struct wmi_block, list); - gblock = &wblock->gblock; - - if ((gblock->flags & ACPI_WMI_EVENT) && - (gblock->notify_id == event)) - return acpi_evaluate_object(wblock->handle, "_WED", - &input, out); - } - - return AE_NOT_FOUND; -} -EXPORT_SYMBOL_GPL(wmi_get_event_data); - -/** - * wmi_has_guid - Check if a GUID is available - * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba - * - * Check if a given GUID is defined by _WDG - */ -bool wmi_has_guid(const char *guid_string) -{ - return find_guid(guid_string, NULL); -} -EXPORT_SYMBOL_GPL(wmi_has_guid); - -/* - * Parse the _WDG method for the GUID data blocks - */ -static __init acpi_status parse_wdg(acpi_handle handle) -{ - struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL}; - union acpi_object *obj; - struct guid_block *gblock; - struct wmi_block *wblock; - acpi_status status; - u32 i, total; - - status = acpi_evaluate_object(handle, "_WDG", NULL, &out); - - if (ACPI_FAILURE(status)) - return status; - - obj = (union acpi_object *) out.pointer; - - if (obj->type != ACPI_TYPE_BUFFER) - return AE_ERROR; - - total = obj->buffer.length / sizeof(struct guid_block); - - gblock = kzalloc(obj->buffer.length, GFP_KERNEL); - if (!gblock) - return AE_NO_MEMORY; - - memcpy(gblock, obj->buffer.pointer, obj->buffer.length); - - for (i = 0; i < total; i++) { - wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL); - if (!wblock) - return AE_NO_MEMORY; - - wblock->gblock = gblock[i]; - wblock->handle = handle; - list_add_tail(&wblock->list, &wmi_blocks.list); - } - - kfree(out.pointer); - kfree(gblock); - - return status; -} - -/* - * WMI can have EmbeddedControl access regions. In which case, we just want to - * hand these off to the EC driver. - */ -static acpi_status -acpi_wmi_ec_space_handler(u32 function, acpi_physical_address address, - u32 bits, acpi_integer * value, - void *handler_context, void *region_context) -{ - int result = 0, i = 0; - u8 temp = 0; - - if ((address > 0xFF) || !value) - return AE_BAD_PARAMETER; - - if (function != ACPI_READ && function != ACPI_WRITE) - return AE_BAD_PARAMETER; - - if (bits != 8) - return AE_BAD_PARAMETER; - - if (function == ACPI_READ) { - result = ec_read(address, &temp); - (*value) |= ((acpi_integer)temp) << i; - } else { - temp = 0xff & ((*value) >> i); - result = ec_write(address, temp); - } - - switch (result) { - case -EINVAL: - return AE_BAD_PARAMETER; - break; - case -ENODEV: - return AE_NOT_FOUND; - break; - case -ETIME: - return AE_TIME; - break; - default: - return AE_OK; - } -} - -static void acpi_wmi_notify(acpi_handle handle, u32 event, void *data) -{ - struct guid_block *block; - struct wmi_block *wblock; - struct list_head *p; - struct acpi_device *device = data; - - list_for_each(p, &wmi_blocks.list) { - wblock = list_entry(p, struct wmi_block, list); - block = &wblock->gblock; - - if ((block->flags & ACPI_WMI_EVENT) && - (block->notify_id == event)) { - if (wblock->handler) - wblock->handler(event, wblock->handler_data); - - acpi_bus_generate_netlink_event( - device->pnp.device_class, device->dev.bus_id, - event, 0); - break; - } - } -} - -static int acpi_wmi_remove(struct acpi_device *device, int type) -{ - acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, - acpi_wmi_notify); - - acpi_remove_address_space_handler(device->handle, - ACPI_ADR_SPACE_EC, &acpi_wmi_ec_space_handler); - - return 0; -} - -static int __init acpi_wmi_add(struct acpi_device *device) -{ - acpi_status status; - int result = 0; - - status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, - acpi_wmi_notify, device); - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX "Error installing notify handler\n"); - return -ENODEV; - } - - status = acpi_install_address_space_handler(device->handle, - ACPI_ADR_SPACE_EC, - &acpi_wmi_ec_space_handler, - NULL, NULL); - if (ACPI_FAILURE(status)) - return -ENODEV; - - status = parse_wdg(device->handle); - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX "Error installing EC region handler\n"); - return -ENODEV; - } - - return result; -} - -static int __init acpi_wmi_init(void) -{ - acpi_status result; - - if (acpi_disabled) - return -ENODEV; - - INIT_LIST_HEAD(&wmi_blocks.list); - - result = acpi_bus_register_driver(&acpi_wmi_driver); - - if (result < 0) { - printk(KERN_INFO PREFIX "Error loading mapper\n"); - } else { - printk(KERN_INFO PREFIX "Mapper loaded\n"); - } - - return result; -} - -static void __exit acpi_wmi_exit(void) -{ - struct list_head *p, *tmp; - struct wmi_block *wblock; - - acpi_bus_unregister_driver(&acpi_wmi_driver); - - list_for_each_safe(p, tmp, &wmi_blocks.list) { - wblock = list_entry(p, struct wmi_block, list); - - list_del(p); - kfree(wblock); - } - - printk(KERN_INFO PREFIX "Mapper unloaded\n"); -} - -subsys_initcall(acpi_wmi_init); -module_exit(acpi_wmi_exit); diff --git a/trunk/drivers/cpuidle/Kconfig b/trunk/drivers/cpuidle/Kconfig index 7dbc4a83c45c..3bed4127d4ad 100644 --- a/trunk/drivers/cpuidle/Kconfig +++ b/trunk/drivers/cpuidle/Kconfig @@ -1,13 +1,13 @@ config CPU_IDLE bool "CPU idle PM support" - default ACPI help CPU idle is a generic framework for supporting software-controlled idle processor power management. It includes modular cross-platform governors that can be swapped during runtime. - If you're using an ACPI-enabled platform, you should say Y here. + If you're using a mobile platform that supports CPU idle PM (e.g. + an ACPI-capable notebook), you should say Y here. config CPU_IDLE_GOV_LADDER bool diff --git a/trunk/drivers/cpuidle/cpuidle.c b/trunk/drivers/cpuidle/cpuidle.c index d868d737742f..2a98d99cbd46 100644 --- a/trunk/drivers/cpuidle/cpuidle.c +++ b/trunk/drivers/cpuidle/cpuidle.c @@ -15,7 +15,6 @@ #include #include #include -#include #include "cpuidle.h" @@ -83,7 +82,7 @@ void cpuidle_uninstall_idle_handler(void) { if (enabled_devices && (pm_idle != pm_idle_old)) { pm_idle = pm_idle_old; - cpuidle_kick_cpus(); + cpu_idle_wait(); } } @@ -181,44 +180,6 @@ void cpuidle_disable_device(struct cpuidle_device *dev) EXPORT_SYMBOL_GPL(cpuidle_disable_device); -#ifdef CONFIG_ARCH_HAS_CPU_RELAX -static int poll_idle(struct cpuidle_device *dev, struct cpuidle_state *st) -{ - ktime_t t1, t2; - s64 diff; - int ret; - - t1 = ktime_get(); - local_irq_enable(); - while (!need_resched()) - cpu_relax(); - - t2 = ktime_get(); - diff = ktime_to_us(ktime_sub(t2, t1)); - if (diff > INT_MAX) - diff = INT_MAX; - - ret = (int) diff; - return ret; -} - -static void poll_idle_init(struct cpuidle_device *dev) -{ - struct cpuidle_state *state = &dev->states[0]; - - cpuidle_set_statedata(state, NULL); - - snprintf(state->name, CPUIDLE_NAME_LEN, "C0 (poll idle)"); - state->exit_latency = 0; - state->target_residency = 0; - state->power_usage = -1; - state->flags = CPUIDLE_FLAG_POLL | CPUIDLE_FLAG_TIME_VALID; - state->enter = poll_idle; -} -#else -static void poll_idle_init(struct cpuidle_device *dev) {} -#endif /* CONFIG_ARCH_HAS_CPU_RELAX */ - /** * cpuidle_register_device - registers a CPU's idle PM feature * @dev: the cpu @@ -237,8 +198,6 @@ int cpuidle_register_device(struct cpuidle_device *dev) mutex_lock(&cpuidle_lock); - poll_idle_init(dev); - per_cpu(cpuidle_devices, dev->cpu) = dev; list_add(&dev->device_list, &cpuidle_detected_devices); if ((ret = cpuidle_add_sysfs(sys_dev))) { diff --git a/trunk/drivers/firmware/dmi_scan.c b/trunk/drivers/firmware/dmi_scan.c index e0bade732376..9008ed5ef4ce 100644 --- a/trunk/drivers/firmware/dmi_scan.c +++ b/trunk/drivers/firmware/dmi_scan.c @@ -489,3 +489,12 @@ int dmi_get_year(int field) return year; } + +/** + * dmi_get_slot - return dmi_ident[slot] + * @slot: index into dmi_ident[] + */ +char *dmi_get_slot(int slot) +{ + return(dmi_ident[slot]); +} diff --git a/trunk/drivers/misc/Kconfig b/trunk/drivers/misc/Kconfig index 78cd33861766..b5e67c0ff433 100644 --- a/trunk/drivers/misc/Kconfig +++ b/trunk/drivers/misc/Kconfig @@ -92,22 +92,6 @@ config TIFM_7XX1 To compile this driver as a module, choose M here: the module will be called tifm_7xx1. -config ACER_WMI - tristate "Acer WMI Laptop Extras (EXPERIMENTAL)" - depends on X86 - depends on EXPERIMENTAL - depends on ACPI - depends on ACPI_WMI - depends on LEDS_CLASS - depends on BACKLIGHT_CLASS_DEVICE - ---help--- - This is a driver for newer Acer (and Wistron) laptops. It adds - wireless radio and bluetooth control, and on some laptops, - exposes the mail LED and LCD backlight. - - If you have an ACPI-WMI compatible Acer/ Wistron laptop, say Y or M - here. - config ASUS_LAPTOP tristate "Asus Laptop Extras (EXPERIMENTAL)" depends on X86 @@ -142,15 +126,6 @@ config FUJITSU_LAPTOP If you have a Fujitsu laptop, say Y or M here. -config TC1100_WMI - tristate "HP Compaq TC1100 Tablet WMI Extras" - depends on X86 && !X86_64 - depends on ACPI - depends on ACPI_WMI - ---help--- - This is a driver for the WMI extensions (wireless and bluetooth power - control) of the HP Compaq TC1100 tablet. - config MSI_LAPTOP tristate "MSI Laptop Extras" depends on X86 @@ -244,25 +219,6 @@ config THINKPAD_ACPI_BAY If you are not sure, say Y here. -config THINKPAD_ACPI_HOTKEY_POLL - bool "Suport NVRAM polling for hot keys" - depends on THINKPAD_ACPI - default y - ---help--- - Some thinkpad models benefit from NVRAM polling to detect a few of - the hot key press events. If you know your ThinkPad model does not - need to do NVRAM polling to support any of the hot keys you use, - unselecting this option will save about 1kB of memory. - - ThinkPads T40 and newer, R52 and newer, and X31 and newer are - unlikely to need NVRAM polling in their latest BIOS versions. - - NVRAM polling can detect at most the following keys: ThinkPad/Access - IBM, Zoom, Switch Display (fn+F7), ThinkLight, Volume up/down/mute, - Brightness up/down, Display Expand (fn+F8), Hibernate (fn+F12). - - If you are not sure, say Y here. The driver enables polling only if - it is strictly necessary to do so. config ATMEL_SSC tristate "Device driver for Atmel SSC peripheral" @@ -276,13 +232,4 @@ config ATMEL_SSC If unsure, say N. -config INTEL_MENLOW - tristate "Thermal Management driver for Intel menlow platform" - depends on ACPI_THERMAL - ---help--- - ACPI thermal management enhancement driver on - Intel Menlow platform. - - If unsure, say N. - endif # MISC_DEVICES diff --git a/trunk/drivers/misc/Makefile b/trunk/drivers/misc/Makefile index 1f41654aae4d..87f2685d728f 100644 --- a/trunk/drivers/misc/Makefile +++ b/trunk/drivers/misc/Makefile @@ -6,10 +6,8 @@ obj- := misc.o # Dummy rule to force built-in.o to be made obj-$(CONFIG_IBM_ASM) += ibmasm/ obj-$(CONFIG_HDPU_FEATURES) += hdpuftrs/ obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o -obj-$(CONFIG_ACER_WMI) += acer-wmi.o obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o obj-$(CONFIG_ATMEL_SSC) += atmel-ssc.o -obj-$(CONFIG_TC1100_WMI) += tc1100-wmi.o obj-$(CONFIG_LKDTM) += lkdtm.o obj-$(CONFIG_TIFM_CORE) += tifm_core.o obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o @@ -19,4 +17,3 @@ obj-$(CONFIG_SONY_LAPTOP) += sony-laptop.o obj-$(CONFIG_THINKPAD_ACPI) += thinkpad_acpi.o obj-$(CONFIG_FUJITSU_LAPTOP) += fujitsu-laptop.o obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o -obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o diff --git a/trunk/drivers/misc/acer-wmi.c b/trunk/drivers/misc/acer-wmi.c deleted file mode 100644 index a4d677504250..000000000000 --- a/trunk/drivers/misc/acer-wmi.c +++ /dev/null @@ -1,1109 +0,0 @@ -/* - * Acer WMI Laptop Extras - * - * Copyright (C) 2007-2008 Carlos Corbacho - * - * Based on acer_acpi: - * Copyright (C) 2005-2007 E.M. Smith - * Copyright (C) 2007-2008 Carlos Corbacho - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define ACER_WMI_VERSION "0.1" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -MODULE_AUTHOR("Carlos Corbacho"); -MODULE_DESCRIPTION("Acer Laptop WMI Extras Driver"); -MODULE_LICENSE("GPL"); - -#define ACER_LOGPREFIX "acer-wmi: " -#define ACER_ERR KERN_ERR ACER_LOGPREFIX -#define ACER_NOTICE KERN_NOTICE ACER_LOGPREFIX -#define ACER_INFO KERN_INFO ACER_LOGPREFIX - -/* - * The following defines quirks to get some specific functions to work - * which are known to not be supported over ACPI-WMI (such as the mail LED - * on WMID based Acer's) - */ -struct acer_quirks { - const char *vendor; - const char *model; - u16 quirks; -}; - -/* - * Magic Number - * Meaning is unknown - this number is required for writing to ACPI for AMW0 - * (it's also used in acerhk when directly accessing the BIOS) - */ -#define ACER_AMW0_WRITE 0x9610 - -/* - * Bit masks for the AMW0 interface - */ -#define ACER_AMW0_WIRELESS_MASK 0x35 -#define ACER_AMW0_BLUETOOTH_MASK 0x34 -#define ACER_AMW0_MAILLED_MASK 0x31 - -/* - * Method IDs for WMID interface - */ -#define ACER_WMID_GET_WIRELESS_METHODID 1 -#define ACER_WMID_GET_BLUETOOTH_METHODID 2 -#define ACER_WMID_GET_BRIGHTNESS_METHODID 3 -#define ACER_WMID_SET_WIRELESS_METHODID 4 -#define ACER_WMID_SET_BLUETOOTH_METHODID 5 -#define ACER_WMID_SET_BRIGHTNESS_METHODID 6 -#define ACER_WMID_GET_THREEG_METHODID 10 -#define ACER_WMID_SET_THREEG_METHODID 11 - -/* - * Acer ACPI method GUIDs - */ -#define AMW0_GUID1 "67C3371D-95A3-4C37-BB61-DD47B491DAAB" -#define WMID_GUID1 "6AF4F258-B401-42fd-BE91-3D4AC2D7C0D3" -#define WMID_GUID2 "95764E09-FB56-4e83-B31A-37761F60994A" - -MODULE_ALIAS("wmi:67C3371D-95A3-4C37-BB61-DD47B491DAAB"); -MODULE_ALIAS("wmi:6AF4F258-B401-42fd-BE91-3D4AC2D7C0D3"); - -/* Temporary workaround until the WMI sysfs interface goes in */ -MODULE_ALIAS("dmi:*:*Acer*:*:"); - -/* - * Interface capability flags - */ -#define ACER_CAP_MAILLED (1<<0) -#define ACER_CAP_WIRELESS (1<<1) -#define ACER_CAP_BLUETOOTH (1<<2) -#define ACER_CAP_BRIGHTNESS (1<<3) -#define ACER_CAP_THREEG (1<<4) -#define ACER_CAP_ANY (0xFFFFFFFF) - -/* - * Interface type flags - */ -enum interface_flags { - ACER_AMW0, - ACER_AMW0_V2, - ACER_WMID, -}; - -#define ACER_DEFAULT_WIRELESS 0 -#define ACER_DEFAULT_BLUETOOTH 0 -#define ACER_DEFAULT_MAILLED 0 -#define ACER_DEFAULT_THREEG 0 - -static int max_brightness = 0xF; - -static int wireless = -1; -static int bluetooth = -1; -static int mailled = -1; -static int brightness = -1; -static int threeg = -1; -static int force_series; - -module_param(mailled, int, 0444); -module_param(wireless, int, 0444); -module_param(bluetooth, int, 0444); -module_param(brightness, int, 0444); -module_param(threeg, int, 0444); -module_param(force_series, int, 0444); -MODULE_PARM_DESC(wireless, "Set initial state of Wireless hardware"); -MODULE_PARM_DESC(bluetooth, "Set initial state of Bluetooth hardware"); -MODULE_PARM_DESC(mailled, "Set initial state of Mail LED"); -MODULE_PARM_DESC(brightness, "Set initial LCD backlight brightness"); -MODULE_PARM_DESC(threeg, "Set initial state of 3G hardware"); -MODULE_PARM_DESC(force_series, "Force a different laptop series"); - -struct acer_data { - int mailled; - int wireless; - int bluetooth; - int threeg; - int brightness; -}; - -/* Each low-level interface must define at least some of the following */ -struct wmi_interface { - /* The WMI device type */ - u32 type; - - /* The capabilities this interface provides */ - u32 capability; - - /* Private data for the current interface */ - struct acer_data data; -}; - -/* The static interface pointer, points to the currently detected interface */ -static struct wmi_interface *interface; - -/* - * Embedded Controller quirks - * Some laptops require us to directly access the EC to either enable or query - * features that are not available through WMI. - */ - -struct quirk_entry { - u8 wireless; - u8 mailled; - u8 brightness; - u8 bluetooth; -}; - -static struct quirk_entry *quirks; - -static void set_quirks(void) -{ - if (quirks->mailled) - interface->capability |= ACER_CAP_MAILLED; - - if (quirks->brightness) - interface->capability |= ACER_CAP_BRIGHTNESS; -} - -static int dmi_matched(const struct dmi_system_id *dmi) -{ - quirks = dmi->driver_data; - return 0; -} - -static struct quirk_entry quirk_unknown = { -}; - -static struct quirk_entry quirk_acer_travelmate_2490 = { - .mailled = 1, -}; - -/* This AMW0 laptop has no bluetooth */ -static struct quirk_entry quirk_medion_md_98300 = { - .wireless = 1, -}; - -static struct dmi_system_id acer_quirks[] = { - { - .callback = dmi_matched, - .ident = "Acer Aspire 3100", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Acer"), - DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 3100"), - }, - .driver_data = &quirk_acer_travelmate_2490, - }, - { - .callback = dmi_matched, - .ident = "Acer Aspire 5100", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Acer"), - DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5100"), - }, - .driver_data = &quirk_acer_travelmate_2490, - }, - { - .callback = dmi_matched, - .ident = "Acer Aspire 5630", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Acer"), - DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5630"), - }, - .driver_data = &quirk_acer_travelmate_2490, - }, - { - .callback = dmi_matched, - .ident = "Acer Aspire 5650", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Acer"), - DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5650"), - }, - .driver_data = &quirk_acer_travelmate_2490, - }, - { - .callback = dmi_matched, - .ident = "Acer Aspire 5680", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Acer"), - DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5680"), - }, - .driver_data = &quirk_acer_travelmate_2490, - }, - { - .callback = dmi_matched, - .ident = "Acer Aspire 9110", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Acer"), - DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 9110"), - }, - .driver_data = &quirk_acer_travelmate_2490, - }, - { - .callback = dmi_matched, - .ident = "Acer TravelMate 2490", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Acer"), - DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 2490"), - }, - .driver_data = &quirk_acer_travelmate_2490, - }, - { - .callback = dmi_matched, - .ident = "Medion MD 98300", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "MEDION"), - DMI_MATCH(DMI_PRODUCT_NAME, "WAM2030"), - }, - .driver_data = &quirk_medion_md_98300, - }, - {} -}; - -/* Find which quirks are needed for a particular vendor/ model pair */ -static void find_quirks(void) -{ - if (!force_series) { - dmi_check_system(acer_quirks); - } else if (force_series == 2490) { - quirks = &quirk_acer_travelmate_2490; - } - - if (quirks == NULL) - quirks = &quirk_unknown; - - set_quirks(); -} - -/* - * General interface convenience methods - */ - -static bool has_cap(u32 cap) -{ - if ((interface->capability & cap) != 0) - return 1; - - return 0; -} - -/* - * AMW0 (V1) interface - */ -struct wmab_args { - u32 eax; - u32 ebx; - u32 ecx; - u32 edx; -}; - -struct wmab_ret { - u32 eax; - u32 ebx; - u32 ecx; - u32 edx; - u32 eex; -}; - -static acpi_status wmab_execute(struct wmab_args *regbuf, -struct acpi_buffer *result) -{ - struct acpi_buffer input; - acpi_status status; - input.length = sizeof(struct wmab_args); - input.pointer = (u8 *)regbuf; - - status = wmi_evaluate_method(AMW0_GUID1, 1, 1, &input, result); - - return status; -} - -static acpi_status AMW0_get_u32(u32 *value, u32 cap, -struct wmi_interface *iface) -{ - int err; - u8 result; - - switch (cap) { - case ACER_CAP_MAILLED: - switch (quirks->mailled) { - default: - err = ec_read(0xA, &result); - if (err) - return AE_ERROR; - *value = (result >> 7) & 0x1; - return AE_OK; - } - break; - case ACER_CAP_WIRELESS: - switch (quirks->wireless) { - case 1: - err = ec_read(0x7B, &result); - if (err) - return AE_ERROR; - *value = result & 0x1; - return AE_OK; - default: - err = ec_read(0xA, &result); - if (err) - return AE_ERROR; - *value = (result >> 2) & 0x1; - return AE_OK; - } - break; - case ACER_CAP_BLUETOOTH: - switch (quirks->bluetooth) { - default: - err = ec_read(0xA, &result); - if (err) - return AE_ERROR; - *value = (result >> 4) & 0x1; - return AE_OK; - } - break; - case ACER_CAP_BRIGHTNESS: - switch (quirks->brightness) { - default: - err = ec_read(0x83, &result); - if (err) - return AE_ERROR; - *value = result; - return AE_OK; - } - break; - default: - return AE_BAD_ADDRESS; - } - return AE_OK; -} - -static acpi_status AMW0_set_u32(u32 value, u32 cap, struct wmi_interface *iface) -{ - struct wmab_args args; - - args.eax = ACER_AMW0_WRITE; - args.ebx = value ? (1<<8) : 0; - args.ecx = args.edx = 0; - - switch (cap) { - case ACER_CAP_MAILLED: - if (value > 1) - return AE_BAD_PARAMETER; - args.ebx |= ACER_AMW0_MAILLED_MASK; - break; - case ACER_CAP_WIRELESS: - if (value > 1) - return AE_BAD_PARAMETER; - args.ebx |= ACER_AMW0_WIRELESS_MASK; - break; - case ACER_CAP_BLUETOOTH: - if (value > 1) - return AE_BAD_PARAMETER; - args.ebx |= ACER_AMW0_BLUETOOTH_MASK; - break; - case ACER_CAP_BRIGHTNESS: - if (value > max_brightness) - return AE_BAD_PARAMETER; - switch (quirks->brightness) { - case 1: - return ec_write(0x83, value); - default: - return AE_BAD_ADDRESS; - break; - } - default: - return AE_BAD_ADDRESS; - } - - /* Actually do the set */ - return wmab_execute(&args, NULL); -} - -static acpi_status AMW0_find_mailled(void) -{ - struct wmab_args args; - struct wmab_ret ret; - acpi_status status = AE_OK; - struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *obj; - - args.eax = 0x86; - args.ebx = args.ecx = args.edx = 0; - - status = wmab_execute(&args, &out); - if (ACPI_FAILURE(status)) - return status; - - obj = (union acpi_object *) out.pointer; - if (obj && obj->type == ACPI_TYPE_BUFFER && - obj->buffer.length == sizeof(struct wmab_ret)) { - ret = *((struct wmab_ret *) obj->buffer.pointer); - } else { - return AE_ERROR; - } - - if (ret.eex & 0x1) - interface->capability |= ACER_CAP_MAILLED; - - kfree(out.pointer); - - return AE_OK; -} - -static acpi_status AMW0_set_capabilities(void) -{ - struct wmab_args args; - struct wmab_ret ret; - acpi_status status = AE_OK; - struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *obj; - - args.eax = ACER_AMW0_WRITE; - args.ecx = args.edx = 0; - - args.ebx = 0xa2 << 8; - args.ebx |= ACER_AMW0_WIRELESS_MASK; - - status = wmab_execute(&args, &out); - if (ACPI_FAILURE(status)) - return status; - - obj = (union acpi_object *) out.pointer; - if (obj && obj->type == ACPI_TYPE_BUFFER && - obj->buffer.length == sizeof(struct wmab_ret)) { - ret = *((struct wmab_ret *) obj->buffer.pointer); - } else { - return AE_ERROR; - } - - if (ret.eax & 0x1) - interface->capability |= ACER_CAP_WIRELESS; - - args.ebx = 2 << 8; - args.ebx |= ACER_AMW0_BLUETOOTH_MASK; - - status = wmab_execute(&args, &out); - if (ACPI_FAILURE(status)) - return status; - - obj = (union acpi_object *) out.pointer; - if (obj && obj->type == ACPI_TYPE_BUFFER - && obj->buffer.length == sizeof(struct wmab_ret)) { - ret = *((struct wmab_ret *) obj->buffer.pointer); - } else { - return AE_ERROR; - } - - if (ret.eax & 0x1) - interface->capability |= ACER_CAP_BLUETOOTH; - - kfree(out.pointer); - - /* - * This appears to be safe to enable, since all Wistron based laptops - * appear to use the same EC register for brightness, even if they - * differ for wireless, etc - */ - interface->capability |= ACER_CAP_BRIGHTNESS; - - return AE_OK; -} - -static struct wmi_interface AMW0_interface = { - .type = ACER_AMW0, -}; - -static struct wmi_interface AMW0_V2_interface = { - .type = ACER_AMW0_V2, -}; - -/* - * New interface (The WMID interface) - */ -static acpi_status -WMI_execute_u32(u32 method_id, u32 in, u32 *out) -{ - struct acpi_buffer input = { (acpi_size) sizeof(u32), (void *)(&in) }; - struct acpi_buffer result = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *obj; - u32 tmp; - acpi_status status; - - status = wmi_evaluate_method(WMID_GUID1, 1, method_id, &input, &result); - - if (ACPI_FAILURE(status)) - return status; - - obj = (union acpi_object *) result.pointer; - if (obj && obj->type == ACPI_TYPE_BUFFER && - obj->buffer.length == sizeof(u32)) { - tmp = *((u32 *) obj->buffer.pointer); - } else { - tmp = 0; - } - - if (out) - *out = tmp; - - kfree(result.pointer); - - return status; -} - -static acpi_status WMID_get_u32(u32 *value, u32 cap, -struct wmi_interface *iface) -{ - acpi_status status; - u8 tmp; - u32 result, method_id = 0; - - switch (cap) { - case ACER_CAP_WIRELESS: - method_id = ACER_WMID_GET_WIRELESS_METHODID; - break; - case ACER_CAP_BLUETOOTH: - method_id = ACER_WMID_GET_BLUETOOTH_METHODID; - break; - case ACER_CAP_BRIGHTNESS: - method_id = ACER_WMID_GET_BRIGHTNESS_METHODID; - break; - case ACER_CAP_THREEG: - method_id = ACER_WMID_GET_THREEG_METHODID; - break; - case ACER_CAP_MAILLED: - if (quirks->mailled == 1) { - ec_read(0x9f, &tmp); - *value = tmp & 0x1; - return 0; - } - default: - return AE_BAD_ADDRESS; - } - status = WMI_execute_u32(method_id, 0, &result); - - if (ACPI_SUCCESS(status)) - *value = (u8)result; - - return status; -} - -static acpi_status WMID_set_u32(u32 value, u32 cap, struct wmi_interface *iface) -{ - u32 method_id = 0; - char param; - - switch (cap) { - case ACER_CAP_BRIGHTNESS: - if (value > max_brightness) - return AE_BAD_PARAMETER; - method_id = ACER_WMID_SET_BRIGHTNESS_METHODID; - break; - case ACER_CAP_WIRELESS: - if (value > 1) - return AE_BAD_PARAMETER; - method_id = ACER_WMID_SET_WIRELESS_METHODID; - break; - case ACER_CAP_BLUETOOTH: - if (value > 1) - return AE_BAD_PARAMETER; - method_id = ACER_WMID_SET_BLUETOOTH_METHODID; - break; - case ACER_CAP_THREEG: - if (value > 1) - return AE_BAD_PARAMETER; - method_id = ACER_WMID_SET_THREEG_METHODID; - break; - case ACER_CAP_MAILLED: - if (value > 1) - return AE_BAD_PARAMETER; - if (quirks->mailled == 1) { - param = value ? 0x92 : 0x93; - i8042_command(¶m, 0x1059); - return 0; - } - break; - default: - return AE_BAD_ADDRESS; - } - return WMI_execute_u32(method_id, (u32)value, NULL); -} - -static acpi_status WMID_set_capabilities(void) -{ - struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL}; - union acpi_object *obj; - acpi_status status; - u32 devices; - - status = wmi_query_block(WMID_GUID2, 1, &out); - if (ACPI_FAILURE(status)) - return status; - - obj = (union acpi_object *) out.pointer; - if (obj && obj->type == ACPI_TYPE_BUFFER && - obj->buffer.length == sizeof(u32)) { - devices = *((u32 *) obj->buffer.pointer); - } else { - return AE_ERROR; - } - - /* Not sure on the meaning of the relevant bits yet to detect these */ - interface->capability |= ACER_CAP_WIRELESS; - interface->capability |= ACER_CAP_THREEG; - - /* WMID always provides brightness methods */ - interface->capability |= ACER_CAP_BRIGHTNESS; - - if (devices & 0x10) - interface->capability |= ACER_CAP_BLUETOOTH; - - if (!(devices & 0x20)) - max_brightness = 0x9; - - return status; -} - -static struct wmi_interface wmid_interface = { - .type = ACER_WMID, -}; - -/* - * Generic Device (interface-independent) - */ - -static acpi_status get_u32(u32 *value, u32 cap) -{ - acpi_status status = AE_BAD_ADDRESS; - - switch (interface->type) { - case ACER_AMW0: - status = AMW0_get_u32(value, cap, interface); - break; - case ACER_AMW0_V2: - if (cap == ACER_CAP_MAILLED) { - status = AMW0_get_u32(value, cap, interface); - break; - } - case ACER_WMID: - status = WMID_get_u32(value, cap, interface); - break; - } - - return status; -} - -static acpi_status set_u32(u32 value, u32 cap) -{ - if (interface->capability & cap) { - switch (interface->type) { - case ACER_AMW0: - return AMW0_set_u32(value, cap, interface); - case ACER_AMW0_V2: - case ACER_WMID: - return WMID_set_u32(value, cap, interface); - default: - return AE_BAD_PARAMETER; - } - } - return AE_BAD_PARAMETER; -} - -static void __init acer_commandline_init(void) -{ - /* - * These will all fail silently if the value given is invalid, or the - * capability isn't available on the given interface - */ - set_u32(mailled, ACER_CAP_MAILLED); - set_u32(wireless, ACER_CAP_WIRELESS); - set_u32(bluetooth, ACER_CAP_BLUETOOTH); - set_u32(threeg, ACER_CAP_THREEG); - set_u32(brightness, ACER_CAP_BRIGHTNESS); -} - -/* - * LED device (Mail LED only, no other LEDs known yet) - */ -static void mail_led_set(struct led_classdev *led_cdev, -enum led_brightness value) -{ - set_u32(value, ACER_CAP_MAILLED); -} - -static struct led_classdev mail_led = { - .name = "acer-mail:green", - .brightness_set = mail_led_set, -}; - -static int __init acer_led_init(struct device *dev) -{ - return led_classdev_register(dev, &mail_led); -} - -static void acer_led_exit(void) -{ - led_classdev_unregister(&mail_led); -} - -/* - * Backlight device - */ -static struct backlight_device *acer_backlight_device; - -static int read_brightness(struct backlight_device *bd) -{ - u32 value; - get_u32(&value, ACER_CAP_BRIGHTNESS); - return value; -} - -static int update_bl_status(struct backlight_device *bd) -{ - set_u32(bd->props.brightness, ACER_CAP_BRIGHTNESS); - return 0; -} - -static struct backlight_ops acer_bl_ops = { - .get_brightness = read_brightness, - .update_status = update_bl_status, -}; - -static int __init acer_backlight_init(struct device *dev) -{ - struct backlight_device *bd; - - bd = backlight_device_register("acer-wmi", dev, NULL, &acer_bl_ops); - if (IS_ERR(bd)) { - printk(ACER_ERR "Could not register Acer backlight device\n"); - acer_backlight_device = NULL; - return PTR_ERR(bd); - } - - acer_backlight_device = bd; - - bd->props.max_brightness = max_brightness; - bd->props.brightness = read_brightness(NULL); - backlight_update_status(bd); - return 0; -} - -static void __exit acer_backlight_exit(void) -{ - backlight_device_unregister(acer_backlight_device); -} - -/* - * Read/ write bool sysfs macro - */ -#define show_set_bool(value, cap) \ -static ssize_t \ -show_bool_##value(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - u32 result; \ - acpi_status status = get_u32(&result, cap); \ - if (ACPI_SUCCESS(status)) \ - return sprintf(buf, "%u\n", result); \ - return sprintf(buf, "Read error\n"); \ -} \ -\ -static ssize_t \ -set_bool_##value(struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - u32 tmp = simple_strtoul(buf, NULL, 10); \ - acpi_status status = set_u32(tmp, cap); \ - if (ACPI_FAILURE(status)) \ - return -EINVAL; \ - return count; \ -} \ -static DEVICE_ATTR(value, S_IWUGO | S_IRUGO | S_IWUSR, \ - show_bool_##value, set_bool_##value); - -show_set_bool(wireless, ACER_CAP_WIRELESS); -show_set_bool(bluetooth, ACER_CAP_BLUETOOTH); -show_set_bool(threeg, ACER_CAP_THREEG); - -/* - * Read interface sysfs macro - */ -static ssize_t show_interface(struct device *dev, struct device_attribute *attr, - char *buf) -{ - switch (interface->type) { - case ACER_AMW0: - return sprintf(buf, "AMW0\n"); - case ACER_AMW0_V2: - return sprintf(buf, "AMW0 v2\n"); - case ACER_WMID: - return sprintf(buf, "WMID\n"); - default: - return sprintf(buf, "Error!\n"); - } -} - -static DEVICE_ATTR(interface, S_IWUGO | S_IRUGO | S_IWUSR, - show_interface, NULL); - -/* - * Platform device - */ -static int __devinit acer_platform_probe(struct platform_device *device) -{ - int err; - - if (has_cap(ACER_CAP_MAILLED)) { - err = acer_led_init(&device->dev); - if (err) - goto error_mailled; - } - - if (has_cap(ACER_CAP_BRIGHTNESS)) { - err = acer_backlight_init(&device->dev); - if (err) - goto error_brightness; - } - - return 0; - -error_brightness: - acer_led_exit(); -error_mailled: - return err; -} - -static int acer_platform_remove(struct platform_device *device) -{ - if (has_cap(ACER_CAP_MAILLED)) - acer_led_exit(); - if (has_cap(ACER_CAP_BRIGHTNESS)) - acer_backlight_exit(); - return 0; -} - -static int acer_platform_suspend(struct platform_device *dev, -pm_message_t state) -{ - u32 value; - struct acer_data *data = &interface->data; - - if (!data) - return -ENOMEM; - - if (has_cap(ACER_CAP_WIRELESS)) { - get_u32(&value, ACER_CAP_WIRELESS); - data->wireless = value; - } - - if (has_cap(ACER_CAP_BLUETOOTH)) { - get_u32(&value, ACER_CAP_BLUETOOTH); - data->bluetooth = value; - } - - if (has_cap(ACER_CAP_MAILLED)) { - get_u32(&value, ACER_CAP_MAILLED); - data->mailled = value; - } - - if (has_cap(ACER_CAP_BRIGHTNESS)) { - get_u32(&value, ACER_CAP_BRIGHTNESS); - data->brightness = value; - } - - return 0; -} - -static int acer_platform_resume(struct platform_device *device) -{ - struct acer_data *data = &interface->data; - - if (!data) - return -ENOMEM; - - if (has_cap(ACER_CAP_WIRELESS)) - set_u32(data->wireless, ACER_CAP_WIRELESS); - - if (has_cap(ACER_CAP_BLUETOOTH)) - set_u32(data->bluetooth, ACER_CAP_BLUETOOTH); - - if (has_cap(ACER_CAP_THREEG)) - set_u32(data->threeg, ACER_CAP_THREEG); - - if (has_cap(ACER_CAP_MAILLED)) - set_u32(data->mailled, ACER_CAP_MAILLED); - - if (has_cap(ACER_CAP_BRIGHTNESS)) - set_u32(data->brightness, ACER_CAP_BRIGHTNESS); - - return 0; -} - -static struct platform_driver acer_platform_driver = { - .driver = { - .name = "acer-wmi", - .owner = THIS_MODULE, - }, - .probe = acer_platform_probe, - .remove = acer_platform_remove, - .suspend = acer_platform_suspend, - .resume = acer_platform_resume, -}; - -static struct platform_device *acer_platform_device; - -static int remove_sysfs(struct platform_device *device) -{ - if (has_cap(ACER_CAP_WIRELESS)) - device_remove_file(&device->dev, &dev_attr_wireless); - - if (has_cap(ACER_CAP_BLUETOOTH)) - device_remove_file(&device->dev, &dev_attr_bluetooth); - - if (has_cap(ACER_CAP_THREEG)) - device_remove_file(&device->dev, &dev_attr_threeg); - - device_remove_file(&device->dev, &dev_attr_interface); - - return 0; -} - -static int create_sysfs(void) -{ - int retval = -ENOMEM; - - if (has_cap(ACER_CAP_WIRELESS)) { - retval = device_create_file(&acer_platform_device->dev, - &dev_attr_wireless); - if (retval) - goto error_sysfs; - } - - if (has_cap(ACER_CAP_BLUETOOTH)) { - retval = device_create_file(&acer_platform_device->dev, - &dev_attr_bluetooth); - if (retval) - goto error_sysfs; - } - - if (has_cap(ACER_CAP_THREEG)) { - retval = device_create_file(&acer_platform_device->dev, - &dev_attr_threeg); - if (retval) - goto error_sysfs; - } - - retval = device_create_file(&acer_platform_device->dev, - &dev_attr_interface); - if (retval) - goto error_sysfs; - - return 0; - -error_sysfs: - remove_sysfs(acer_platform_device); - return retval; -} - -static int __init acer_wmi_init(void) -{ - int err; - - printk(ACER_INFO "Acer Laptop ACPI-WMI Extras version %s\n", - ACER_WMI_VERSION); - - /* - * Detect which ACPI-WMI interface we're using. - */ - if (wmi_has_guid(AMW0_GUID1) && wmi_has_guid(WMID_GUID1)) - interface = &AMW0_V2_interface; - - if (!wmi_has_guid(AMW0_GUID1) && wmi_has_guid(WMID_GUID1)) - interface = &wmid_interface; - - if (wmi_has_guid(WMID_GUID2) && interface) { - if (ACPI_FAILURE(WMID_set_capabilities())) { - printk(ACER_ERR "Unable to detect available devices\n"); - return -ENODEV; - } - } else if (!wmi_has_guid(WMID_GUID2) && interface) { - printk(ACER_ERR "Unable to detect available devices\n"); - return -ENODEV; - } - - if (wmi_has_guid(AMW0_GUID1) && !wmi_has_guid(WMID_GUID1)) { - interface = &AMW0_interface; - - if (ACPI_FAILURE(AMW0_set_capabilities())) { - printk(ACER_ERR "Unable to detect available devices\n"); - return -ENODEV; - } - } - - if (wmi_has_guid(AMW0_GUID1)) { - if (ACPI_FAILURE(AMW0_find_mailled())) - printk(ACER_ERR "Unable to detect mail LED\n"); - } - - find_quirks(); - - if (!interface) { - printk(ACER_ERR "No or unsupported WMI interface, unable to "); - printk(KERN_CONT "load.\n"); - return -ENODEV; - } - - if (platform_driver_register(&acer_platform_driver)) { - printk(ACER_ERR "Unable to register platform driver.\n"); - goto error_platform_register; - } - acer_platform_device = platform_device_alloc("acer-wmi", -1); - platform_device_add(acer_platform_device); - - err = create_sysfs(); - if (err) - return err; - - /* Override any initial settings with values from the commandline */ - acer_commandline_init(); - - return 0; - -error_platform_register: - return -ENODEV; -} - -static void __exit acer_wmi_exit(void) -{ - remove_sysfs(acer_platform_device); - platform_device_del(acer_platform_device); - platform_driver_unregister(&acer_platform_driver); - - printk(ACER_INFO "Acer Laptop WMI Extras unloaded\n"); - return; -} - -module_init(acer_wmi_init); -module_exit(acer_wmi_exit); diff --git a/trunk/drivers/misc/asus-laptop.c b/trunk/drivers/misc/asus-laptop.c index 3bd883166e3d..0846c33296bc 100644 --- a/trunk/drivers/misc/asus-laptop.c +++ b/trunk/drivers/misc/asus-laptop.c @@ -254,7 +254,7 @@ ASUS_LED(gled, "gaming"); * method is searched within the scope of the handle, can be NULL. The output * of the method is written is output, which can also be NULL * - * returns 0 if write is successful, -1 else. + * returns 1 if write is successful, 0 else. */ static int write_acpi_int(acpi_handle handle, const char *method, int val, struct acpi_buffer *output) @@ -263,19 +263,13 @@ static int write_acpi_int(acpi_handle handle, const char *method, int val, union acpi_object in_obj; //the only param we use acpi_status status; - if (!handle) - return 0; - params.count = 1; params.pointer = &in_obj; in_obj.type = ACPI_TYPE_INTEGER; in_obj.integer.value = val; status = acpi_evaluate_object(handle, (char *)method, ¶ms, output); - if (status == AE_OK) - return 0; - else - return -1; + return (status == AE_OK); } static int read_wireless_status(int mask) @@ -327,7 +321,7 @@ static void write_status(acpi_handle handle, int out, int mask) switch (mask) { case MLED_ON: - out = !(out & 0x1); + out = !out & 0x1; break; case GLED_ON: out = (out & 0x1) + 1; @@ -341,7 +335,7 @@ static void write_status(acpi_handle handle, int out, int mask) break; } - if (write_acpi_int(handle, NULL, out, NULL)) + if (handle && !write_acpi_int(handle, NULL, out, NULL)) printk(ASUS_WARNING " write failed %x\n", mask); } @@ -421,7 +415,7 @@ static int set_brightness(struct backlight_device *bd, int value) value = (0 < value) ? ((15 < value) ? 15 : value) : 0; /* 0 <= value <= 15 */ - if (write_acpi_int(brightness_set_handle, NULL, value, NULL)) { + if (!write_acpi_int(brightness_set_handle, NULL, value, NULL)) { printk(ASUS_WARNING "Error changing brightness\n"); ret = -EIO; } @@ -551,7 +545,7 @@ static ssize_t store_ledd(struct device *dev, struct device_attribute *attr, rv = parse_arg(buf, count, &value); if (rv > 0) { - if (write_acpi_int(ledd_set_handle, NULL, value, NULL)) + if (!write_acpi_int(ledd_set_handle, NULL, value, NULL)) printk(ASUS_WARNING "LED display write failed\n"); else hotk->ledd_status = (u32) value; @@ -596,7 +590,7 @@ static ssize_t store_bluetooth(struct device *dev, static void set_display(int value) { /* no sanity check needed for now */ - if (write_acpi_int(display_set_handle, NULL, value, NULL)) + if (!write_acpi_int(display_set_handle, NULL, value, NULL)) printk(ASUS_WARNING "Error setting display\n"); return; } @@ -653,7 +647,7 @@ static ssize_t store_disp(struct device *dev, struct device_attribute *attr, */ static void set_light_sens_switch(int value) { - if (write_acpi_int(ls_switch_handle, NULL, value, NULL)) + if (!write_acpi_int(ls_switch_handle, NULL, value, NULL)) printk(ASUS_WARNING "Error setting light sensor switch\n"); hotk->light_switch = value; } @@ -678,7 +672,7 @@ static ssize_t store_lssw(struct device *dev, struct device_attribute *attr, static void set_light_sens_level(int value) { - if (write_acpi_int(ls_level_handle, NULL, value, NULL)) + if (!write_acpi_int(ls_level_handle, NULL, value, NULL)) printk(ASUS_WARNING "Error setting light sensor level\n"); hotk->light_level = value; } @@ -866,7 +860,7 @@ static int asus_hotk_get_info(void) printk(ASUS_WARNING "Couldn't get the DSDT table header\n"); /* We have to write 0 on init this far for all ASUS models */ - if (write_acpi_int(hotk->handle, "INIT", 0, &buffer)) { + if (!write_acpi_int(hotk->handle, "INIT", 0, &buffer)) { printk(ASUS_ERR "Hotkey initialization failed\n"); return -ENODEV; } diff --git a/trunk/drivers/misc/intel_menlow.c b/trunk/drivers/misc/intel_menlow.c deleted file mode 100644 index f70984ab1e1b..000000000000 --- a/trunk/drivers/misc/intel_menlow.c +++ /dev/null @@ -1,526 +0,0 @@ -/* - * intel_menlow.c - Intel menlow Driver for thermal management extension - * - * Copyright (C) 2008 Intel Corp - * Copyright (C) 2008 Sujith Thomas - * Copyright (C) 2008 Zhang Rui - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This driver creates the sys I/F for programming the sensors. - * It also implements the driver for intel menlow memory controller (hardware - * id is INT0002) which makes use of the platform specific ACPI methods - * to get/set bandwidth. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -MODULE_AUTHOR("Thomas Sujith"); -MODULE_AUTHOR("Zhang Rui"); -MODULE_DESCRIPTION("Intel Menlow platform specific driver"); -MODULE_LICENSE("GPL"); - -/* - * Memory controller device control - */ - -#define MEMORY_GET_BANDWIDTH "GTHS" -#define MEMORY_SET_BANDWIDTH "STHS" -#define MEMORY_ARG_CUR_BANDWIDTH 1 -#define MEMORY_ARG_MAX_BANDWIDTH 0 - -static int memory_get_int_max_bandwidth(struct thermal_cooling_device *cdev, - unsigned long *max_state) -{ - struct acpi_device *device = cdev->devdata; - acpi_handle handle = device->handle; - unsigned long value; - struct acpi_object_list arg_list; - union acpi_object arg; - acpi_status status = AE_OK; - - arg_list.count = 1; - arg_list.pointer = &arg; - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = MEMORY_ARG_MAX_BANDWIDTH; - status = acpi_evaluate_integer(handle, MEMORY_GET_BANDWIDTH, - &arg_list, &value); - if (ACPI_FAILURE(status)) - return -EFAULT; - - *max_state = value - 1; - return 0; -} - -static int memory_get_max_bandwidth(struct thermal_cooling_device *cdev, - char *buf) -{ - unsigned long value; - if (memory_get_int_max_bandwidth(cdev, &value)) - return -EINVAL; - - return sprintf(buf, "%ld\n", value); -} - -static int memory_get_cur_bandwidth(struct thermal_cooling_device *cdev, - char *buf) -{ - struct acpi_device *device = cdev->devdata; - acpi_handle handle = device->handle; - unsigned long value; - struct acpi_object_list arg_list; - union acpi_object arg; - acpi_status status = AE_OK; - - arg_list.count = 1; - arg_list.pointer = &arg; - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = MEMORY_ARG_CUR_BANDWIDTH; - status = acpi_evaluate_integer(handle, MEMORY_GET_BANDWIDTH, - &arg_list, &value); - if (ACPI_FAILURE(status)) - return -EFAULT; - - return sprintf(buf, "%ld\n", value); -} - -static int memory_set_cur_bandwidth(struct thermal_cooling_device *cdev, - unsigned int state) -{ - struct acpi_device *device = cdev->devdata; - acpi_handle handle = device->handle; - struct acpi_object_list arg_list; - union acpi_object arg; - acpi_status status; - int temp; - unsigned long max_state; - - if (memory_get_int_max_bandwidth(cdev, &max_state)) - return -EFAULT; - - if (max_state < 0 || state > max_state) - return -EINVAL; - - arg_list.count = 1; - arg_list.pointer = &arg; - arg.type = ACPI_TYPE_INTEGER; - arg.integer.value = state; - - status = - acpi_evaluate_integer(handle, MEMORY_SET_BANDWIDTH, &arg_list, - (unsigned long *)&temp); - - printk(KERN_INFO - "Bandwidth value was %d: status is %d\n", state, status); - if (ACPI_FAILURE(status)) - return -EFAULT; - - return 0; -} - -static struct thermal_cooling_device_ops memory_cooling_ops = { - .get_max_state = memory_get_max_bandwidth, - .get_cur_state = memory_get_cur_bandwidth, - .set_cur_state = memory_set_cur_bandwidth, -}; - -/* - * Memory Device Management - */ -static int intel_menlow_memory_add(struct acpi_device *device) -{ - int result = -ENODEV; - acpi_status status = AE_OK; - acpi_handle dummy; - struct thermal_cooling_device *cdev; - - if (!device) - return -EINVAL; - - status = acpi_get_handle(device->handle, MEMORY_GET_BANDWIDTH, &dummy); - if (ACPI_FAILURE(status)) - goto end; - - status = acpi_get_handle(device->handle, MEMORY_SET_BANDWIDTH, &dummy); - if (ACPI_FAILURE(status)) - goto end; - - cdev = thermal_cooling_device_register("Memory controller", device, - &memory_cooling_ops); - acpi_driver_data(device) = cdev; - if (!cdev) - result = -ENODEV; - else { - result = sysfs_create_link(&device->dev.kobj, - &cdev->device.kobj, "thermal_cooling"); - if (result) - goto unregister; - - result = sysfs_create_link(&cdev->device.kobj, - &device->dev.kobj, "device"); - if (result) { - sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); - goto unregister; - } - } - - end: - return result; - - unregister: - thermal_cooling_device_unregister(cdev); - return result; - -} - -static int intel_menlow_memory_remove(struct acpi_device *device, int type) -{ - struct thermal_cooling_device *cdev = acpi_driver_data(device); - - if (!device || !cdev) - return -EINVAL; - - sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); - sysfs_remove_link(&cdev->device.kobj, "device"); - thermal_cooling_device_unregister(cdev); - - return 0; -} - -const static struct acpi_device_id intel_menlow_memory_ids[] = { - {"INT0002", 0}, - {"", 0}, -}; - -static struct acpi_driver intel_menlow_memory_driver = { - .name = "intel_menlow_thermal_control", - .ids = intel_menlow_memory_ids, - .ops = { - .add = intel_menlow_memory_add, - .remove = intel_menlow_memory_remove, - }, -}; - -/* - * Sensor control on menlow platform - */ - -#define THERMAL_AUX0 0 -#define THERMAL_AUX1 1 -#define GET_AUX0 "GAX0" -#define GET_AUX1 "GAX1" -#define SET_AUX0 "SAX0" -#define SET_AUX1 "SAX1" - -struct intel_menlow_attribute { - struct device_attribute attr; - struct device *device; - acpi_handle handle; - struct list_head node; -}; - -static LIST_HEAD(intel_menlow_attr_list); -static DEFINE_MUTEX(intel_menlow_attr_lock); - -/* - * sensor_get_auxtrip - get the current auxtrip value from sensor - * @name: Thermalzone name - * @auxtype : AUX0/AUX1 - * @buf: syfs buffer - */ -static int sensor_get_auxtrip(acpi_handle handle, int index, int *value) -{ - acpi_status status; - - if ((index != 0 && index != 1) || !value) - return -EINVAL; - - status = acpi_evaluate_integer(handle, index ? GET_AUX1 : GET_AUX0, - NULL, (unsigned long *)value); - if (ACPI_FAILURE(status)) - return -EIO; - - return 0; -} - -/* - * sensor_set_auxtrip - set the new auxtrip value to sensor - * @name: Thermalzone name - * @auxtype : AUX0/AUX1 - * @buf: syfs buffer - */ -static int sensor_set_auxtrip(acpi_handle handle, int index, int value) -{ - acpi_status status; - union acpi_object arg = { - ACPI_TYPE_INTEGER - }; - struct acpi_object_list args = { - 1, &arg - }; - int temp; - - if (index != 0 && index != 1) - return -EINVAL; - - status = acpi_evaluate_integer(handle, index ? GET_AUX0 : GET_AUX1, - NULL, (unsigned long *)&temp); - if (ACPI_FAILURE(status)) - return -EIO; - if ((index && value < temp) || (!index && value > temp)) - return -EINVAL; - - arg.integer.value = value; - status = acpi_evaluate_integer(handle, index ? SET_AUX1 : SET_AUX0, - &args, (unsigned long *)&temp); - if (ACPI_FAILURE(status)) - return -EIO; - - /* do we need to check the return value of SAX0/SAX1 ? */ - - return 0; -} - -#define to_intel_menlow_attr(_attr) \ - container_of(_attr, struct intel_menlow_attribute, attr) - -static ssize_t aux0_show(struct device *dev, - struct device_attribute *dev_attr, char *buf) -{ - struct intel_menlow_attribute *attr = to_intel_menlow_attr(dev_attr); - int value; - int result; - - result = sensor_get_auxtrip(attr->handle, 0, &value); - - return result ? result : sprintf(buf, "%lu", KELVIN_TO_CELSIUS(value)); -} - -static ssize_t aux1_show(struct device *dev, - struct device_attribute *dev_attr, char *buf) -{ - struct intel_menlow_attribute *attr = to_intel_menlow_attr(dev_attr); - int value; - int result; - - result = sensor_get_auxtrip(attr->handle, 1, &value); - - return result ? result : sprintf(buf, "%lu", KELVIN_TO_CELSIUS(value)); -} - -static ssize_t aux0_store(struct device *dev, - struct device_attribute *dev_attr, - const char *buf, size_t count) -{ - struct intel_menlow_attribute *attr = to_intel_menlow_attr(dev_attr); - int value; - int result; - - /*Sanity check; should be a positive integer */ - if (!sscanf(buf, "%d", &value)) - return -EINVAL; - - if (value < 0) - return -EINVAL; - - result = sensor_set_auxtrip(attr->handle, 0, CELSIUS_TO_KELVIN(value)); - return result ? result : count; -} - -static ssize_t aux1_store(struct device *dev, - struct device_attribute *dev_attr, - const char *buf, size_t count) -{ - struct intel_menlow_attribute *attr = to_intel_menlow_attr(dev_attr); - int value; - int result; - - /*Sanity check; should be a positive integer */ - if (!sscanf(buf, "%d", &value)) - return -EINVAL; - - if (value < 0) - return -EINVAL; - - result = sensor_set_auxtrip(attr->handle, 1, CELSIUS_TO_KELVIN(value)); - return result ? result : count; -} - -/* BIOS can enable/disable the thermal user application in dabney platform */ -#define BIOS_ENABLED "\\_TZ.GSTS" -static ssize_t bios_enabled_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - acpi_status status; - unsigned long bios_enabled; - - status = acpi_evaluate_integer(NULL, BIOS_ENABLED, NULL, &bios_enabled); - if (ACPI_FAILURE(status)) - return -ENODEV; - - return sprintf(buf, "%s\n", bios_enabled ? "enabled" : "disabled"); -} - -static int intel_menlow_add_one_attribute(char *name, int mode, void *show, - void *store, struct device *dev, - acpi_handle handle) -{ - struct intel_menlow_attribute *attr; - int result; - - attr = kzalloc(sizeof(struct intel_menlow_attribute), GFP_KERNEL); - if (!attr) - return -ENOMEM; - - attr->attr.attr.name = name; - attr->attr.attr.mode = mode; - attr->attr.show = show; - attr->attr.store = store; - attr->device = dev; - attr->handle = handle; - - result = device_create_file(dev, &attr->attr); - if (result) - return result; - - mutex_lock(&intel_menlow_attr_lock); - list_add_tail(&attr->node, &intel_menlow_attr_list); - mutex_unlock(&intel_menlow_attr_lock); - - return 0; -} - -static acpi_status intel_menlow_register_sensor(acpi_handle handle, u32 lvl, - void *context, void **rv) -{ - acpi_status status; - acpi_handle dummy; - struct thermal_zone_device *thermal; - int result; - - result = acpi_bus_get_private_data(handle, (void **)&thermal); - if (result) - return 0; - - /* _TZ must have the AUX0/1 methods */ - status = acpi_get_handle(handle, GET_AUX0, &dummy); - if (ACPI_FAILURE(status)) - goto not_found; - - status = acpi_get_handle(handle, SET_AUX0, &dummy); - if (ACPI_FAILURE(status)) - goto not_found; - - result = intel_menlow_add_one_attribute("aux0", 0644, - aux0_show, aux0_store, - &thermal->device, handle); - if (result) - return AE_ERROR; - - status = acpi_get_handle(handle, GET_AUX1, &dummy); - if (ACPI_FAILURE(status)) - goto not_found; - - status = acpi_get_handle(handle, SET_AUX1, &dummy); - if (ACPI_FAILURE(status)) - goto not_found; - - result = intel_menlow_add_one_attribute("aux1", 0644, - aux1_show, aux1_store, - &thermal->device, handle); - if (result) - return AE_ERROR; - - /* - * create the "dabney_enabled" attribute which means the user app - * should be loaded or not - */ - - result = intel_menlow_add_one_attribute("bios_enabled", 0444, - bios_enabled_show, NULL, - &thermal->device, handle); - if (result) - return AE_ERROR; - - not_found: - if (status == AE_NOT_FOUND) - return AE_OK; - else - return status; -} - -static void intel_menlow_unregister_sensor(void) -{ - struct intel_menlow_attribute *pos, *next; - - mutex_lock(&intel_menlow_attr_lock); - list_for_each_entry_safe(pos, next, &intel_menlow_attr_list, node) { - list_del(&pos->node); - device_remove_file(pos->device, &pos->attr); - kfree(pos); - } - mutex_unlock(&intel_menlow_attr_lock); - - return; -} - -static int __init intel_menlow_module_init(void) -{ - int result = -ENODEV; - acpi_status status; - unsigned long enable; - - if (acpi_disabled) - return result; - - /* Looking for the \_TZ.GSTS method */ - status = acpi_evaluate_integer(NULL, BIOS_ENABLED, NULL, &enable); - if (ACPI_FAILURE(status) || !enable) - return -ENODEV; - - /* Looking for ACPI device MEM0 with hardware id INT0002 */ - result = acpi_bus_register_driver(&intel_menlow_memory_driver); - if (result) - return result; - - /* Looking for sensors in each ACPI thermal zone */ - status = acpi_walk_namespace(ACPI_TYPE_THERMAL, ACPI_ROOT_OBJECT, - ACPI_UINT32_MAX, - intel_menlow_register_sensor, NULL, NULL); - if (ACPI_FAILURE(status)) - return -ENODEV; - - return 0; -} - -static void __exit intel_menlow_module_exit(void) -{ - acpi_bus_unregister_driver(&intel_menlow_memory_driver); - intel_menlow_unregister_sensor(); -} - -module_init(intel_menlow_module_init); -module_exit(intel_menlow_module_exit); diff --git a/trunk/drivers/misc/sony-laptop.c b/trunk/drivers/misc/sony-laptop.c index 899e3f75f288..b0f68031b49d 100644 --- a/trunk/drivers/misc/sony-laptop.c +++ b/trunk/drivers/misc/sony-laptop.c @@ -73,7 +73,7 @@ if (debug) printk(KERN_WARNING DRV_PFX msg); \ } while (0) -#define SONY_LAPTOP_DRIVER_VERSION "0.6" +#define SONY_LAPTOP_DRIVER_VERSION "0.5" #define SONY_NC_CLASS "sony-nc" #define SONY_NC_HID "SNY5001" @@ -146,70 +146,68 @@ struct sony_laptop_keypress { * and input layer indexes in the keymap */ static int sony_laptop_input_index[] = { - -1, /* 0 no event */ - -1, /* 1 SONYPI_EVENT_JOGDIAL_DOWN */ - -1, /* 2 SONYPI_EVENT_JOGDIAL_UP */ - -1, /* 3 SONYPI_EVENT_JOGDIAL_DOWN_PRESSED */ - -1, /* 4 SONYPI_EVENT_JOGDIAL_UP_PRESSED */ - -1, /* 5 SONYPI_EVENT_JOGDIAL_PRESSED */ - -1, /* 6 SONYPI_EVENT_JOGDIAL_RELEASED */ - 0, /* 7 SONYPI_EVENT_CAPTURE_PRESSED */ - 1, /* 8 SONYPI_EVENT_CAPTURE_RELEASED */ - 2, /* 9 SONYPI_EVENT_CAPTURE_PARTIALPRESSED */ - 3, /* 10 SONYPI_EVENT_CAPTURE_PARTIALRELEASED */ - 4, /* 11 SONYPI_EVENT_FNKEY_ESC */ - 5, /* 12 SONYPI_EVENT_FNKEY_F1 */ - 6, /* 13 SONYPI_EVENT_FNKEY_F2 */ - 7, /* 14 SONYPI_EVENT_FNKEY_F3 */ - 8, /* 15 SONYPI_EVENT_FNKEY_F4 */ - 9, /* 16 SONYPI_EVENT_FNKEY_F5 */ - 10, /* 17 SONYPI_EVENT_FNKEY_F6 */ - 11, /* 18 SONYPI_EVENT_FNKEY_F7 */ - 12, /* 19 SONYPI_EVENT_FNKEY_F8 */ - 13, /* 20 SONYPI_EVENT_FNKEY_F9 */ - 14, /* 21 SONYPI_EVENT_FNKEY_F10 */ - 15, /* 22 SONYPI_EVENT_FNKEY_F11 */ - 16, /* 23 SONYPI_EVENT_FNKEY_F12 */ - 17, /* 24 SONYPI_EVENT_FNKEY_1 */ - 18, /* 25 SONYPI_EVENT_FNKEY_2 */ - 19, /* 26 SONYPI_EVENT_FNKEY_D */ - 20, /* 27 SONYPI_EVENT_FNKEY_E */ - 21, /* 28 SONYPI_EVENT_FNKEY_F */ - 22, /* 29 SONYPI_EVENT_FNKEY_S */ - 23, /* 30 SONYPI_EVENT_FNKEY_B */ - 24, /* 31 SONYPI_EVENT_BLUETOOTH_PRESSED */ - 25, /* 32 SONYPI_EVENT_PKEY_P1 */ - 26, /* 33 SONYPI_EVENT_PKEY_P2 */ - 27, /* 34 SONYPI_EVENT_PKEY_P3 */ - 28, /* 35 SONYPI_EVENT_BACK_PRESSED */ - -1, /* 36 SONYPI_EVENT_LID_CLOSED */ - -1, /* 37 SONYPI_EVENT_LID_OPENED */ - 29, /* 38 SONYPI_EVENT_BLUETOOTH_ON */ - 30, /* 39 SONYPI_EVENT_BLUETOOTH_OFF */ - 31, /* 40 SONYPI_EVENT_HELP_PRESSED */ - 32, /* 41 SONYPI_EVENT_FNKEY_ONLY */ - 33, /* 42 SONYPI_EVENT_JOGDIAL_FAST_DOWN */ - 34, /* 43 SONYPI_EVENT_JOGDIAL_FAST_UP */ - 35, /* 44 SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED */ - 36, /* 45 SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED */ - 37, /* 46 SONYPI_EVENT_JOGDIAL_VFAST_DOWN */ - 38, /* 47 SONYPI_EVENT_JOGDIAL_VFAST_UP */ - 39, /* 48 SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED */ - 40, /* 49 SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED */ - 41, /* 50 SONYPI_EVENT_ZOOM_PRESSED */ - 42, /* 51 SONYPI_EVENT_THUMBPHRASE_PRESSED */ - 43, /* 52 SONYPI_EVENT_MEYE_FACE */ - 44, /* 53 SONYPI_EVENT_MEYE_OPPOSITE */ - 45, /* 54 SONYPI_EVENT_MEMORYSTICK_INSERT */ - 46, /* 55 SONYPI_EVENT_MEMORYSTICK_EJECT */ - -1, /* 56 SONYPI_EVENT_ANYBUTTON_RELEASED */ - -1, /* 57 SONYPI_EVENT_BATTERY_INSERT */ - -1, /* 58 SONYPI_EVENT_BATTERY_REMOVE */ - -1, /* 59 SONYPI_EVENT_FNKEY_RELEASED */ - 47, /* 60 SONYPI_EVENT_WIRELESS_ON */ - 48, /* 61 SONYPI_EVENT_WIRELESS_OFF */ - 49, /* 62 SONYPI_EVENT_ZOOM_IN_PRESSED */ - 50, /* 63 SONYPI_EVENT_ZOOM_OUT_PRESSED */ + -1, /* no event */ + -1, /* SONYPI_EVENT_JOGDIAL_DOWN */ + -1, /* SONYPI_EVENT_JOGDIAL_UP */ + -1, /* SONYPI_EVENT_JOGDIAL_DOWN_PRESSED */ + -1, /* SONYPI_EVENT_JOGDIAL_UP_PRESSED */ + -1, /* SONYPI_EVENT_JOGDIAL_PRESSED */ + -1, /* SONYPI_EVENT_JOGDIAL_RELEASED */ + 0, /* SONYPI_EVENT_CAPTURE_PRESSED */ + 1, /* SONYPI_EVENT_CAPTURE_RELEASED */ + 2, /* SONYPI_EVENT_CAPTURE_PARTIALPRESSED */ + 3, /* SONYPI_EVENT_CAPTURE_PARTIALRELEASED */ + 4, /* SONYPI_EVENT_FNKEY_ESC */ + 5, /* SONYPI_EVENT_FNKEY_F1 */ + 6, /* SONYPI_EVENT_FNKEY_F2 */ + 7, /* SONYPI_EVENT_FNKEY_F3 */ + 8, /* SONYPI_EVENT_FNKEY_F4 */ + 9, /* SONYPI_EVENT_FNKEY_F5 */ + 10, /* SONYPI_EVENT_FNKEY_F6 */ + 11, /* SONYPI_EVENT_FNKEY_F7 */ + 12, /* SONYPI_EVENT_FNKEY_F8 */ + 13, /* SONYPI_EVENT_FNKEY_F9 */ + 14, /* SONYPI_EVENT_FNKEY_F10 */ + 15, /* SONYPI_EVENT_FNKEY_F11 */ + 16, /* SONYPI_EVENT_FNKEY_F12 */ + 17, /* SONYPI_EVENT_FNKEY_1 */ + 18, /* SONYPI_EVENT_FNKEY_2 */ + 19, /* SONYPI_EVENT_FNKEY_D */ + 20, /* SONYPI_EVENT_FNKEY_E */ + 21, /* SONYPI_EVENT_FNKEY_F */ + 22, /* SONYPI_EVENT_FNKEY_S */ + 23, /* SONYPI_EVENT_FNKEY_B */ + 24, /* SONYPI_EVENT_BLUETOOTH_PRESSED */ + 25, /* SONYPI_EVENT_PKEY_P1 */ + 26, /* SONYPI_EVENT_PKEY_P2 */ + 27, /* SONYPI_EVENT_PKEY_P3 */ + 28, /* SONYPI_EVENT_BACK_PRESSED */ + -1, /* SONYPI_EVENT_LID_CLOSED */ + -1, /* SONYPI_EVENT_LID_OPENED */ + 29, /* SONYPI_EVENT_BLUETOOTH_ON */ + 30, /* SONYPI_EVENT_BLUETOOTH_OFF */ + 31, /* SONYPI_EVENT_HELP_PRESSED */ + 32, /* SONYPI_EVENT_FNKEY_ONLY */ + 33, /* SONYPI_EVENT_JOGDIAL_FAST_DOWN */ + 34, /* SONYPI_EVENT_JOGDIAL_FAST_UP */ + 35, /* SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED */ + 36, /* SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED */ + 37, /* SONYPI_EVENT_JOGDIAL_VFAST_DOWN */ + 38, /* SONYPI_EVENT_JOGDIAL_VFAST_UP */ + 39, /* SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED */ + 40, /* SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED */ + 41, /* SONYPI_EVENT_ZOOM_PRESSED */ + 42, /* SONYPI_EVENT_THUMBPHRASE_PRESSED */ + 43, /* SONYPI_EVENT_MEYE_FACE */ + 44, /* SONYPI_EVENT_MEYE_OPPOSITE */ + 45, /* SONYPI_EVENT_MEMORYSTICK_INSERT */ + 46, /* SONYPI_EVENT_MEMORYSTICK_EJECT */ + -1, /* SONYPI_EVENT_ANYBUTTON_RELEASED */ + -1, /* SONYPI_EVENT_BATTERY_INSERT */ + -1, /* SONYPI_EVENT_BATTERY_REMOVE */ + -1, /* SONYPI_EVENT_FNKEY_RELEASED */ + 47, /* SONYPI_EVENT_WIRELESS_ON */ + 48, /* SONYPI_EVENT_WIRELESS_OFF */ }; static int sony_laptop_input_keycode_map[] = { @@ -262,8 +260,6 @@ static int sony_laptop_input_keycode_map[] = { KEY_RESERVED, /* 46 SONYPI_EVENT_MEMORYSTICK_EJECT */ KEY_WLAN, /* 47 SONYPI_EVENT_WIRELESS_ON */ KEY_WLAN, /* 48 SONYPI_EVENT_WIRELESS_OFF */ - KEY_ZOOMIN, /* 49 SONYPI_EVENT_ZOOM_IN_PRESSED */ - KEY_ZOOMOUT /* 50 SONYPI_EVENT_ZOOM_OUT_PRESSED */ }; /* release buttons after a short delay if pressed */ @@ -315,7 +311,7 @@ static void sony_laptop_report_input_event(u8 event) break; default: - if (event > ARRAY_SIZE(sony_laptop_input_index)) { + if (event > ARRAY_SIZE (sony_laptop_input_keycode_map)) { dprintk("sony_laptop_report_input_event, event not known: %d\n", event); break; } @@ -879,15 +875,6 @@ static const struct dmi_system_id sony_nc_ids[] = { DMI_MATCH(DMI_PRODUCT_NAME, "VGN-C"), }, }, - { - .ident = "Sony Vaio N Series", - .callback = sony_nc_C_enable, - .driver_data = sony_C_events, - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VGN-N"), - }, - }, { } }; @@ -1182,12 +1169,10 @@ static struct acpi_driver sony_nc_driver = { #define SONYPI_DEVICE_TYPE1 0x00000001 #define SONYPI_DEVICE_TYPE2 0x00000002 #define SONYPI_DEVICE_TYPE3 0x00000004 -#define SONYPI_DEVICE_TYPE4 0x00000008 #define SONYPI_TYPE1_OFFSET 0x04 #define SONYPI_TYPE2_OFFSET 0x12 #define SONYPI_TYPE3_OFFSET 0x12 -#define SONYPI_TYPE4_OFFSET 0x12 struct sony_pic_ioport { struct acpi_resource_io io1; @@ -1200,33 +1185,18 @@ struct sony_pic_irq { struct list_head list; }; -struct sonypi_eventtypes { - u8 data; - unsigned long mask; - struct sonypi_event *events; -}; - -struct device_ctrl { - int model; - int (*handle_irq)(const u8, const u8); - u16 evport_offset; - u8 has_camera; - u8 has_bluetooth; - u8 has_wwan; - struct sonypi_eventtypes *event_types; -}; - struct sony_pic_dev { - struct device_ctrl *control; + int model; + u16 evport_offset; + u8 camera_power; + u8 bluetooth_power; + u8 wwan_power; struct acpi_device *acpi_dev; struct sony_pic_irq *cur_irq; struct sony_pic_ioport *cur_ioport; struct list_head interrupts; struct list_head ioports; struct mutex lock; - u8 camera_power; - u8 bluetooth_power; - u8 wwan_power; }; static struct sony_pic_dev spic_dev = { @@ -1283,7 +1253,6 @@ static struct sonypi_event sonypi_joggerev[] = { static struct sonypi_event sonypi_captureev[] = { { 0x05, SONYPI_EVENT_CAPTURE_PARTIALPRESSED }, { 0x07, SONYPI_EVENT_CAPTURE_PRESSED }, - { 0x40, SONYPI_EVENT_CAPTURE_PRESSED }, { 0x01, SONYPI_EVENT_CAPTURE_PARTIALRELEASED }, { 0, 0 } }; @@ -1320,6 +1289,7 @@ static struct sonypi_event sonypi_pkeyev[] = { { 0x01, SONYPI_EVENT_PKEY_P1 }, { 0x02, SONYPI_EVENT_PKEY_P2 }, { 0x04, SONYPI_EVENT_PKEY_P3 }, + { 0x5c, SONYPI_EVENT_PKEY_P1 }, { 0, 0 } }; @@ -1361,8 +1331,6 @@ static struct sonypi_event sonypi_lidev[] = { /* The set of possible zoom events */ static struct sonypi_event sonypi_zoomev[] = { { 0x39, SONYPI_EVENT_ZOOM_PRESSED }, - { 0x10, SONYPI_EVENT_ZOOM_IN_PRESSED }, - { 0x20, SONYPI_EVENT_ZOOM_OUT_PRESSED }, { 0, 0 } }; @@ -1393,58 +1361,76 @@ static struct sonypi_event sonypi_batteryev[] = { { 0, 0 } }; -static struct sonypi_eventtypes type1_events[] = { - { 0, 0xffffffff, sonypi_releaseev }, - { 0x70, SONYPI_MEYE_MASK, sonypi_meyeev }, - { 0x30, SONYPI_LID_MASK, sonypi_lidev }, - { 0x60, SONYPI_CAPTURE_MASK, sonypi_captureev }, - { 0x10, SONYPI_JOGGER_MASK, sonypi_joggerev }, - { 0x20, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, - { 0x30, SONYPI_BLUETOOTH_MASK, sonypi_blueev }, - { 0x40, SONYPI_PKEY_MASK, sonypi_pkeyev }, - { 0x30, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, - { 0x40, SONYPI_BATTERY_MASK, sonypi_batteryev }, - { 0 }, -}; -static struct sonypi_eventtypes type2_events[] = { - { 0, 0xffffffff, sonypi_releaseev }, - { 0x38, SONYPI_LID_MASK, sonypi_lidev }, - { 0x11, SONYPI_JOGGER_MASK, sonypi_joggerev }, - { 0x61, SONYPI_CAPTURE_MASK, sonypi_captureev }, - { 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, - { 0x31, SONYPI_BLUETOOTH_MASK, sonypi_blueev }, - { 0x08, SONYPI_PKEY_MASK, sonypi_pkeyev }, - { 0x11, SONYPI_BACK_MASK, sonypi_backev }, - { 0x21, SONYPI_HELP_MASK, sonypi_helpev }, - { 0x21, SONYPI_ZOOM_MASK, sonypi_zoomev }, - { 0x20, SONYPI_THUMBPHRASE_MASK, sonypi_thumbphraseev }, - { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, - { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, - { 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, - { 0 }, -}; -static struct sonypi_eventtypes type3_events[] = { - { 0, 0xffffffff, sonypi_releaseev }, - { 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, - { 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev }, - { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, - { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, - { 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, - { 0 }, -}; -static struct sonypi_eventtypes type4_events[] = { - { 0, 0xffffffff, sonypi_releaseev }, - { 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, - { 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev }, - { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, - { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, - { 0x05, SONYPI_PKEY_MASK, sonypi_pkeyev }, - { 0x05, SONYPI_ZOOM_MASK, sonypi_zoomev }, - { 0x05, SONYPI_CAPTURE_MASK, sonypi_captureev }, - { 0 }, +static struct sonypi_eventtypes { + int model; + u8 data; + unsigned long mask; + struct sonypi_event * events; +} sony_pic_eventtypes[] = { + { SONYPI_DEVICE_TYPE1, 0, 0xffffffff, sonypi_releaseev }, + { SONYPI_DEVICE_TYPE1, 0x70, SONYPI_MEYE_MASK, sonypi_meyeev }, + { SONYPI_DEVICE_TYPE1, 0x30, SONYPI_LID_MASK, sonypi_lidev }, + { SONYPI_DEVICE_TYPE1, 0x60, SONYPI_CAPTURE_MASK, sonypi_captureev }, + { SONYPI_DEVICE_TYPE1, 0x10, SONYPI_JOGGER_MASK, sonypi_joggerev }, + { SONYPI_DEVICE_TYPE1, 0x20, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, + { SONYPI_DEVICE_TYPE1, 0x30, SONYPI_BLUETOOTH_MASK, sonypi_blueev }, + { SONYPI_DEVICE_TYPE1, 0x40, SONYPI_PKEY_MASK, sonypi_pkeyev }, + { SONYPI_DEVICE_TYPE1, 0x30, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, + { SONYPI_DEVICE_TYPE1, 0x40, SONYPI_BATTERY_MASK, sonypi_batteryev }, + + { SONYPI_DEVICE_TYPE2, 0, 0xffffffff, sonypi_releaseev }, + { SONYPI_DEVICE_TYPE2, 0x38, SONYPI_LID_MASK, sonypi_lidev }, + { SONYPI_DEVICE_TYPE2, 0x11, SONYPI_JOGGER_MASK, sonypi_joggerev }, + { SONYPI_DEVICE_TYPE2, 0x61, SONYPI_CAPTURE_MASK, sonypi_captureev }, + { SONYPI_DEVICE_TYPE2, 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, + { SONYPI_DEVICE_TYPE2, 0x31, SONYPI_BLUETOOTH_MASK, sonypi_blueev }, + { SONYPI_DEVICE_TYPE2, 0x08, SONYPI_PKEY_MASK, sonypi_pkeyev }, + { SONYPI_DEVICE_TYPE2, 0x11, SONYPI_BACK_MASK, sonypi_backev }, + { SONYPI_DEVICE_TYPE2, 0x21, SONYPI_HELP_MASK, sonypi_helpev }, + { SONYPI_DEVICE_TYPE2, 0x21, SONYPI_ZOOM_MASK, sonypi_zoomev }, + { SONYPI_DEVICE_TYPE2, 0x20, SONYPI_THUMBPHRASE_MASK, sonypi_thumbphraseev }, + { SONYPI_DEVICE_TYPE2, 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, + { SONYPI_DEVICE_TYPE2, 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, + { SONYPI_DEVICE_TYPE2, 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, + + { SONYPI_DEVICE_TYPE3, 0, 0xffffffff, sonypi_releaseev }, + { SONYPI_DEVICE_TYPE3, 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, + { SONYPI_DEVICE_TYPE3, 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev }, + { SONYPI_DEVICE_TYPE3, 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, + { SONYPI_DEVICE_TYPE3, 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, + { SONYPI_DEVICE_TYPE3, 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, + { 0 } }; -/* low level spic calls */ +static int sony_pic_detect_device_type(void) +{ + struct pci_dev *pcidev; + int model = 0; + + if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82371AB_3, NULL))) + model = SONYPI_DEVICE_TYPE1; + + else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_ICH6_1, NULL))) + model = SONYPI_DEVICE_TYPE3; + + else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_ICH7_1, NULL))) + model = SONYPI_DEVICE_TYPE3; + + else + model = SONYPI_DEVICE_TYPE2; + + if (pcidev) + pci_dev_put(pcidev); + + printk(KERN_INFO DRV_PFX "detected Type%d model\n", + model == SONYPI_DEVICE_TYPE1 ? 1 : + model == SONYPI_DEVICE_TYPE2 ? 2 : 3); + return model; +} + #define ITERATIONS_LONG 10000 #define ITERATIONS_SHORT 10 #define wait_on_command(command, iterations) { \ @@ -1465,7 +1451,7 @@ static u8 sony_pic_call1(u8 dev) outb(dev, spic_dev.cur_ioport->io1.minimum + 4); v1 = inb_p(spic_dev.cur_ioport->io1.minimum + 4); v2 = inb_p(spic_dev.cur_ioport->io1.minimum); - dprintk("sony_pic_call1(0x%.2x): 0x%.4x\n", dev, (v2 << 8) | v1); + dprintk("sony_pic_call1: 0x%.4x\n", (v2 << 8) | v1); return v2; } @@ -1480,7 +1466,7 @@ static u8 sony_pic_call2(u8 dev, u8 fn) ITERATIONS_LONG); outb(fn, spic_dev.cur_ioport->io1.minimum); v1 = inb_p(spic_dev.cur_ioport->io1.minimum); - dprintk("sony_pic_call2(0x%.2x - 0x%.2x): 0x%.4x\n", dev, fn, v1); + dprintk("sony_pic_call2: 0x%.4x\n", v1); return v1; } @@ -1495,105 +1481,10 @@ static u8 sony_pic_call3(u8 dev, u8 fn, u8 v) wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG); outb(v, spic_dev.cur_ioport->io1.minimum); v1 = inb_p(spic_dev.cur_ioport->io1.minimum); - dprintk("sony_pic_call3(0x%.2x - 0x%.2x - 0x%.2x): 0x%.4x\n", - dev, fn, v, v1); + dprintk("sony_pic_call3: 0x%.4x\n", v1); return v1; } -/* - * minidrivers for SPIC models - */ -static int type4_handle_irq(const u8 data_mask, const u8 ev) -{ - /* - * 0x31 could mean we have to take some extra action and wait for - * the next irq for some Type4 models, it will generate a new - * irq and we can read new data from the device: - * - 0x5c and 0x5f requires 0xA0 - * - 0x61 requires 0xB3 - */ - if (data_mask == 0x31) { - if (ev == 0x5c || ev == 0x5f) - sony_pic_call1(0xA0); - else if (ev == 0x61) - sony_pic_call1(0xB3); - return 0; - } - return 1; -} - -static struct device_ctrl spic_types[] = { - { - .model = SONYPI_DEVICE_TYPE1, - .handle_irq = NULL, - .evport_offset = SONYPI_TYPE1_OFFSET, - .event_types = type1_events, - }, - { - .model = SONYPI_DEVICE_TYPE2, - .handle_irq = NULL, - .evport_offset = SONYPI_TYPE2_OFFSET, - .event_types = type2_events, - }, - { - .model = SONYPI_DEVICE_TYPE3, - .handle_irq = NULL, - .evport_offset = SONYPI_TYPE3_OFFSET, - .event_types = type3_events, - }, - { - .model = SONYPI_DEVICE_TYPE4, - .handle_irq = type4_handle_irq, - .evport_offset = SONYPI_TYPE4_OFFSET, - .event_types = type4_events, - }, -}; - -static void sony_pic_detect_device_type(struct sony_pic_dev *dev) -{ - struct pci_dev *pcidev; - - pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_82371AB_3, NULL); - if (pcidev) { - dev->control = &spic_types[0]; - goto out; - } - - pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_ICH6_1, NULL); - if (pcidev) { - dev->control = &spic_types[2]; - goto out; - } - - pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_ICH7_1, NULL); - if (pcidev) { - dev->control = &spic_types[3]; - goto out; - } - - pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_ICH8_4, NULL); - if (pcidev) { - dev->control = &spic_types[3]; - goto out; - } - - /* default */ - dev->control = &spic_types[1]; - -out: - if (pcidev) - pci_dev_put(pcidev); - - printk(KERN_INFO DRV_PFX "detected Type%d model\n", - dev->control->model == SONYPI_DEVICE_TYPE1 ? 1 : - dev->control->model == SONYPI_DEVICE_TYPE2 ? 2 : - dev->control->model == SONYPI_DEVICE_TYPE3 ? 3 : 4); -} - /* camera tests and poweron/poweroff */ #define SONYPI_CAMERA_PICTURE 5 #define SONYPI_CAMERA_CONTROL 0x10 @@ -2362,7 +2253,7 @@ static int sony_pic_enable(struct acpi_device *device, buffer.pointer = resource; /* setup Type 1 resources */ - if (spic_dev.control->model == SONYPI_DEVICE_TYPE1) { + if (spic_dev.model == SONYPI_DEVICE_TYPE1) { /* setup io resources */ resource->res1.type = ACPI_RESOURCE_TYPE_IO; @@ -2444,49 +2335,39 @@ static irqreturn_t sony_pic_irq(int irq, void *dev_id) if (dev->cur_ioport->io2.minimum) data_mask = inb_p(dev->cur_ioport->io2.minimum); else - data_mask = inb_p(dev->cur_ioport->io1.minimum + - dev->control->evport_offset); + data_mask = inb_p(dev->cur_ioport->io1.minimum + dev->evport_offset); dprintk("event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n", - ev, data_mask, dev->cur_ioport->io1.minimum, - dev->control->evport_offset); + ev, data_mask, dev->cur_ioport->io1.minimum, dev->evport_offset); if (ev == 0x00 || ev == 0xff) return IRQ_HANDLED; - for (i = 0; dev->control->event_types[i].mask; i++) { + for (i = 0; sony_pic_eventtypes[i].model; i++) { + + if (spic_dev.model != sony_pic_eventtypes[i].model) + continue; - if ((data_mask & dev->control->event_types[i].data) != - dev->control->event_types[i].data) + if ((data_mask & sony_pic_eventtypes[i].data) != + sony_pic_eventtypes[i].data) continue; - if (!(mask & dev->control->event_types[i].mask)) + if (!(mask & sony_pic_eventtypes[i].mask)) continue; - for (j = 0; dev->control->event_types[i].events[j].event; j++) { - if (ev == dev->control->event_types[i].events[j].data) { + for (j = 0; sony_pic_eventtypes[i].events[j].event; j++) { + if (ev == sony_pic_eventtypes[i].events[j].data) { device_event = - dev->control-> - event_types[i].events[j].event; + sony_pic_eventtypes[i].events[j].event; goto found; } } } - /* Still not able to decode the event try to pass - * it over to the minidriver - */ - if (dev->control->handle_irq && - dev->control->handle_irq(data_mask, ev) == 0) - return IRQ_HANDLED; - - dprintk("unknown event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n", - ev, data_mask, dev->cur_ioport->io1.minimum, - dev->control->evport_offset); return IRQ_HANDLED; found: sony_laptop_report_input_event(device_event); - acpi_bus_generate_proc_event(dev->acpi_dev, 1, device_event); + acpi_bus_generate_proc_event(spic_dev.acpi_dev, 1, device_event); sonypi_compat_report_event(device_event); return IRQ_HANDLED; @@ -2548,9 +2429,23 @@ static int sony_pic_add(struct acpi_device *device) spic_dev.acpi_dev = device; strcpy(acpi_device_class(device), "sony/hotkey"); - sony_pic_detect_device_type(&spic_dev); + spic_dev.model = sony_pic_detect_device_type(); mutex_init(&spic_dev.lock); + /* model specific characteristics */ + switch(spic_dev.model) { + case SONYPI_DEVICE_TYPE1: + spic_dev.evport_offset = SONYPI_TYPE1_OFFSET; + break; + case SONYPI_DEVICE_TYPE3: + spic_dev.evport_offset = SONYPI_TYPE3_OFFSET; + break; + case SONYPI_DEVICE_TYPE2: + default: + spic_dev.evport_offset = SONYPI_TYPE2_OFFSET; + break; + } + /* read _PRS resources */ result = sony_pic_possible_resources(device); if (result) { diff --git a/trunk/drivers/misc/tc1100-wmi.c b/trunk/drivers/misc/tc1100-wmi.c deleted file mode 100644 index f25e4c974dcf..000000000000 --- a/trunk/drivers/misc/tc1100-wmi.c +++ /dev/null @@ -1,290 +0,0 @@ -/* - * HP Compaq TC1100 Tablet WMI Extras Driver - * - * Copyright (C) 2007 Carlos Corbacho - * Copyright (C) 2004 Jamey Hicks - * Copyright (C) 2001, 2002 Andy Grover - * Copyright (C) 2001, 2002 Paul Diefenbaugh - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define GUID "C364AC71-36DB-495A-8494-B439D472A505" - -#define TC1100_INSTANCE_WIRELESS 1 -#define TC1100_INSTANCE_JOGDIAL 2 - -#define TC1100_LOGPREFIX "tc1100-wmi: " -#define TC1100_INFO KERN_INFO TC1100_LOGPREFIX - -MODULE_AUTHOR("Jamey Hicks, Carlos Corbacho"); -MODULE_DESCRIPTION("HP Compaq TC1100 Tablet WMI Extras"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("wmi:C364AC71-36DB-495A-8494-B439D472A505"); - -static int tc1100_probe(struct platform_device *device); -static int tc1100_remove(struct platform_device *device); -static int tc1100_suspend(struct platform_device *device, pm_message_t state); -static int tc1100_resume(struct platform_device *device); - -static struct platform_driver tc1100_driver = { - .driver = { - .name = "tc1100-wmi", - .owner = THIS_MODULE, - }, - .probe = tc1100_probe, - .remove = tc1100_remove, - .suspend = tc1100_suspend, - .resume = tc1100_resume, -}; - -static struct platform_device *tc1100_device; - -struct tc1100_data { - u32 wireless; - u32 jogdial; -}; - -static struct tc1100_data suspend_data; - -/* -------------------------------------------------------------------------- - Device Management - -------------------------------------------------------------------------- */ - -static int get_state(u32 *out, u8 instance) -{ - u32 tmp; - acpi_status status; - struct acpi_buffer result = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *obj; - - if (!out) - return -EINVAL; - - if (instance > 2) - return -ENODEV; - - status = wmi_query_block(GUID, instance, &result); - if (ACPI_FAILURE(status)) - return -ENODEV; - - obj = (union acpi_object *) result.pointer; - if (obj && obj->type == ACPI_TYPE_BUFFER && - obj->buffer.length == sizeof(u32)) { - tmp = *((u32 *) obj->buffer.pointer); - } else { - tmp = 0; - } - - if (result.length > 0 && result.pointer) - kfree(result.pointer); - - switch (instance) { - case TC1100_INSTANCE_WIRELESS: - *out = (tmp == 3) ? 1 : 0; - return 0; - case TC1100_INSTANCE_JOGDIAL: - *out = (tmp == 1) ? 1 : 0; - return 0; - default: - return -ENODEV; - } -} - -static int set_state(u32 *in, u8 instance) -{ - u32 value; - acpi_status status; - struct acpi_buffer input; - - if (!in) - return -EINVAL; - - if (instance > 2) - return -ENODEV; - - switch (instance) { - case TC1100_INSTANCE_WIRELESS: - value = (*in) ? 1 : 2; - break; - case TC1100_INSTANCE_JOGDIAL: - value = (*in) ? 0 : 1; - break; - default: - return -ENODEV; - } - - input.length = sizeof(u32); - input.pointer = &value; - - status = wmi_set_block(GUID, instance, &input); - if (ACPI_FAILURE(status)) - return -ENODEV; - - return 0; -} - -/* -------------------------------------------------------------------------- - FS Interface (/sys) - -------------------------------------------------------------------------- */ - -/* - * Read/ write bool sysfs macro - */ -#define show_set_bool(value, instance) \ -static ssize_t \ -show_bool_##value(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - u32 result; \ - acpi_status status = get_state(&result, instance); \ - if (ACPI_SUCCESS(status)) \ - return sprintf(buf, "%d\n", result); \ - return sprintf(buf, "Read error\n"); \ -} \ -\ -static ssize_t \ -set_bool_##value(struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - u32 tmp = simple_strtoul(buf, NULL, 10); \ - acpi_status status = set_state(&tmp, instance); \ - if (ACPI_FAILURE(status)) \ - return -EINVAL; \ - return count; \ -} \ -static DEVICE_ATTR(value, S_IWUGO | S_IRUGO | S_IWUSR, \ - show_bool_##value, set_bool_##value); - -show_set_bool(wireless, TC1100_INSTANCE_WIRELESS); -show_set_bool(jogdial, TC1100_INSTANCE_JOGDIAL); - -static void remove_fs(void) -{ - device_remove_file(&tc1100_device->dev, &dev_attr_wireless); - device_remove_file(&tc1100_device->dev, &dev_attr_jogdial); -} - -static int add_fs(void) -{ - int ret; - - ret = device_create_file(&tc1100_device->dev, &dev_attr_wireless); - if (ret) - goto add_sysfs_error; - - ret = device_create_file(&tc1100_device->dev, &dev_attr_jogdial); - if (ret) - goto add_sysfs_error; - - return ret; - -add_sysfs_error: - remove_fs(); - return ret; -} - -/* -------------------------------------------------------------------------- - Driver Model - -------------------------------------------------------------------------- */ - -static int tc1100_probe(struct platform_device *device) -{ - int result = 0; - - result = add_fs(); - return result; -} - - -static int tc1100_remove(struct platform_device *device) -{ - remove_fs(); - return 0; -} - -static int tc1100_suspend(struct platform_device *dev, pm_message_t state) -{ - int ret; - - ret = get_state(&suspend_data.wireless, TC1100_INSTANCE_WIRELESS); - if (ret) - return ret; - - ret = get_state(&suspend_data.jogdial, TC1100_INSTANCE_JOGDIAL); - if (ret) - return ret; - - return ret; -} - -static int tc1100_resume(struct platform_device *dev) -{ - int ret; - - ret = set_state(&suspend_data.wireless, TC1100_INSTANCE_WIRELESS); - if (ret) - return ret; - - ret = set_state(&suspend_data.jogdial, TC1100_INSTANCE_JOGDIAL); - if (ret) - return ret; - - return ret; -} - -static int __init tc1100_init(void) -{ - int result = 0; - - if (!wmi_has_guid(GUID)) - return -ENODEV; - - result = platform_driver_register(&tc1100_driver); - if (result) - return result; - - tc1100_device = platform_device_alloc("tc1100-wmi", -1); - platform_device_add(tc1100_device); - - printk(TC1100_INFO "HP Compaq TC1100 Tablet WMI Extras loaded\n"); - - return result; -} - -static void __exit tc1100_exit(void) -{ - platform_device_del(tc1100_device); - platform_driver_unregister(&tc1100_driver); - - printk(TC1100_INFO "HP Compaq TC1100 Tablet WMI Extras unloaded\n"); -} - -module_init(tc1100_init); -module_exit(tc1100_exit); diff --git a/trunk/drivers/misc/thinkpad_acpi.c b/trunk/drivers/misc/thinkpad_acpi.c index 7ba1acad5402..cf56647a6ca4 100644 --- a/trunk/drivers/misc/thinkpad_acpi.c +++ b/trunk/drivers/misc/thinkpad_acpi.c @@ -3,7 +3,7 @@ * * * Copyright (C) 2004-2005 Borislav Deianov - * Copyright (C) 2006-2008 Henrique de Moraes Holschuh + * Copyright (C) 2006-2007 Henrique de Moraes Holschuh * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,13 +21,11 @@ * 02110-1301, USA. */ -#define TPACPI_VERSION "0.19" -#define TPACPI_SYSFS_VERSION 0x020200 +#define IBM_VERSION "0.17" +#define TPACPI_SYSFS_VERSION 0x020000 /* * Changelog: - * 2007-10-20 changelog trimmed down - * * 2007-03-27 0.14 renamed to thinkpad_acpi and moved to * drivers/misc. * @@ -35,219 +33,89 @@ * changelog now lives in git commit history, and will * not be updated further in-file. * + * 2005-08-17 0.12 fix compilation on 2.6.13-rc kernels * 2005-03-17 0.11 support for 600e, 770x * thanks to Jamie Lentin - * - * 2005-01-16 0.9 use MODULE_VERSION + * support for 770e, G41 + * G40 and G41 don't have a thinklight + * temperatures no longer experimental + * experimental brightness control + * experimental volume control + * experimental fan enable/disable + * 2005-01-16 0.10 fix module loading on R30, R31 + * 2005-01-16 0.9 support for 570, R30, R31 + * ultrabay support on A22p, A3x + * limit arg for cmos, led, beep, drop experimental status + * more capable led control on A21e, A22p, T20-22, X20 + * experimental temperatures and fan speed + * experimental embedded controller register dump + * mark more functions as __init, drop incorrect __exit + * use MODULE_VERSION * thanks to Henrik Brix Andersen * fix parameter passing on module loading * thanks to Rusty Russell * thanks to Jim Radford * 2004-11-08 0.8 fix init error case, don't return from a macro * thanks to Chris Wright + * 2004-10-23 0.7 fix module loading on A21e, A22p, T20, T21, X20 + * fix led control on A21e + * 2004-10-19 0.6 use acpi_bus_register_driver() to claim HKEY device + * 2004-10-18 0.5 thinklight support on A21e, G40, R32, T20, T21, X20 + * proc file format changed + * video_switch command + * experimental cmos control + * experimental led control + * experimental acpi sounds + * 2004-09-16 0.4 support for module parameters + * hotkey mask can be prefixed by 0x + * video output switching + * video expansion control + * ultrabay eject support + * removed lcd brightness/on/off control, didn't work + * 2004-08-17 0.3 support for R40 + * lcd off, brightness control + * thinklight on/off + * 2004-08-14 0.2 support for T series, X20 + * bluetooth enable/disable + * hotkey events disabled by default + * removed fan control, currently useless + * 2004-08-09 0.1 initial release, support for X series */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include - - -/* ThinkPad CMOS commands */ -#define TP_CMOS_VOLUME_DOWN 0 -#define TP_CMOS_VOLUME_UP 1 -#define TP_CMOS_VOLUME_MUTE 2 -#define TP_CMOS_BRIGHTNESS_UP 4 -#define TP_CMOS_BRIGHTNESS_DOWN 5 - -/* NVRAM Addresses */ -enum tp_nvram_addr { - TP_NVRAM_ADDR_HK2 = 0x57, - TP_NVRAM_ADDR_THINKLIGHT = 0x58, - TP_NVRAM_ADDR_VIDEO = 0x59, - TP_NVRAM_ADDR_BRIGHTNESS = 0x5e, - TP_NVRAM_ADDR_MIXER = 0x60, -}; - -/* NVRAM bit masks */ -enum { - TP_NVRAM_MASK_HKT_THINKPAD = 0x08, - TP_NVRAM_MASK_HKT_ZOOM = 0x20, - TP_NVRAM_MASK_HKT_DISPLAY = 0x40, - TP_NVRAM_MASK_HKT_HIBERNATE = 0x80, - TP_NVRAM_MASK_THINKLIGHT = 0x10, - TP_NVRAM_MASK_HKT_DISPEXPND = 0x30, - TP_NVRAM_MASK_HKT_BRIGHTNESS = 0x20, - TP_NVRAM_MASK_LEVEL_BRIGHTNESS = 0x0f, - TP_NVRAM_POS_LEVEL_BRIGHTNESS = 0, - TP_NVRAM_MASK_MUTE = 0x40, - TP_NVRAM_MASK_HKT_VOLUME = 0x80, - TP_NVRAM_MASK_LEVEL_VOLUME = 0x0f, - TP_NVRAM_POS_LEVEL_VOLUME = 0, -}; - -/* ACPI HIDs */ -#define TPACPI_ACPI_HKEY_HID "IBM0068" - -/* Input IDs */ -#define TPACPI_HKEY_INPUT_PRODUCT 0x5054 /* "TP" */ -#define TPACPI_HKEY_INPUT_VERSION 0x4101 - - -/**************************************************************************** - * Main driver - */ - -#define TPACPI_NAME "thinkpad" -#define TPACPI_DESC "ThinkPad ACPI Extras" -#define TPACPI_FILE TPACPI_NAME "_acpi" -#define TPACPI_URL "http://ibm-acpi.sf.net/" -#define TPACPI_MAIL "ibm-acpi-devel@lists.sourceforge.net" - -#define TPACPI_PROC_DIR "ibm" -#define TPACPI_ACPI_EVENT_PREFIX "ibm" -#define TPACPI_DRVR_NAME TPACPI_FILE -#define TPACPI_HWMON_DRVR_NAME TPACPI_NAME "_hwmon" - -#define TPACPI_MAX_ACPI_ARGS 3 - -/* Debugging */ -#define TPACPI_LOG TPACPI_FILE ": " -#define TPACPI_ERR KERN_ERR TPACPI_LOG -#define TPACPI_NOTICE KERN_NOTICE TPACPI_LOG -#define TPACPI_INFO KERN_INFO TPACPI_LOG -#define TPACPI_DEBUG KERN_DEBUG TPACPI_LOG - -#define TPACPI_DBG_ALL 0xffff -#define TPACPI_DBG_ALL 0xffff -#define TPACPI_DBG_INIT 0x0001 -#define TPACPI_DBG_EXIT 0x0002 -#define dbg_printk(a_dbg_level, format, arg...) \ - do { if (dbg_level & a_dbg_level) \ - printk(TPACPI_DEBUG "%s: " format, __func__ , ## arg); \ - } while (0) -#ifdef CONFIG_THINKPAD_ACPI_DEBUG -#define vdbg_printk(a_dbg_level, format, arg...) \ - dbg_printk(a_dbg_level, format, ## arg) -static const char *str_supported(int is_supported); -#else -#define vdbg_printk(a_dbg_level, format, arg...) -#endif +#include "thinkpad_acpi.h" -#define onoff(status, bit) ((status) & (1 << (bit)) ? "on" : "off") -#define enabled(status, bit) ((status) & (1 << (bit)) ? "enabled" : "disabled") -#define strlencmp(a, b) (strncmp((a), (b), strlen(b))) +MODULE_AUTHOR("Borislav Deianov, Henrique de Moraes Holschuh"); +MODULE_DESCRIPTION(IBM_DESC); +MODULE_VERSION(IBM_VERSION); +MODULE_LICENSE("GPL"); +/* Please remove this in year 2009 */ +MODULE_ALIAS("ibm_acpi"); -/**************************************************************************** - * Driver-wide structs and misc. variables +/* + * DMI matching for module autoloading + * + * See http://thinkwiki.org/wiki/List_of_DMI_IDs + * See http://thinkwiki.org/wiki/BIOS_Upgrade_Downloads + * + * Only models listed in thinkwiki will be supported, so add yours + * if it is not there yet. */ +#define IBM_BIOS_MODULE_ALIAS(__type) \ + MODULE_ALIAS("dmi:bvnIBM:bvr" __type "ET??WW") -struct ibm_struct; - -struct tp_acpi_drv_struct { - const struct acpi_device_id *hid; - struct acpi_driver *driver; - - void (*notify) (struct ibm_struct *, u32); - acpi_handle *handle; - u32 type; - struct acpi_device *device; -}; - -struct ibm_struct { - char *name; - - int (*read) (char *); - int (*write) (char *); - void (*exit) (void); - void (*resume) (void); - void (*suspend) (pm_message_t state); - - struct list_head all_drivers; - - struct tp_acpi_drv_struct *acpi; - - struct { - u8 acpi_driver_registered:1; - u8 acpi_notify_installed:1; - u8 proc_created:1; - u8 init_called:1; - u8 experimental:1; - } flags; -}; - -struct ibm_init_struct { - char param[32]; +/* Non-ancient thinkpads */ +MODULE_ALIAS("dmi:bvnIBM:*:svnIBM:*:pvrThinkPad*:rvnIBM:*"); +MODULE_ALIAS("dmi:bvnLENOVO:*:svnLENOVO:*:pvrThinkPad*:rvnLENOVO:*"); - int (*init) (struct ibm_init_struct *); - struct ibm_struct *data; -}; +/* Ancient thinkpad BIOSes have to be identified by + * BIOS type or model number, and there are far less + * BIOS types than model numbers... */ +IBM_BIOS_MODULE_ALIAS("I[B,D,H,I,M,N,O,T,W,V,Y,Z]"); +IBM_BIOS_MODULE_ALIAS("1[0,3,6,8,A-G,I,K,M-P,S,T]"); +IBM_BIOS_MODULE_ALIAS("K[U,X-Z]"); -static struct { -#ifdef CONFIG_THINKPAD_ACPI_BAY - u32 bay_status:1; - u32 bay_eject:1; - u32 bay_status2:1; - u32 bay_eject2:1; -#endif - u32 bluetooth:1; - u32 hotkey:1; - u32 hotkey_mask:1; - u32 hotkey_wlsw:1; - u32 light:1; - u32 light_status:1; - u32 bright_16levels:1; - u32 wan:1; - u32 fan_ctrl_status_undef:1; - u32 input_device_registered:1; - u32 platform_drv_registered:1; - u32 platform_drv_attrs_registered:1; - u32 sensors_pdrv_registered:1; - u32 sensors_pdrv_attrs_registered:1; - u32 sensors_pdev_attrs_registered:1; - u32 hotkey_poll_active:1; -} tp_features; - -struct thinkpad_id_data { - unsigned int vendor; /* ThinkPad vendor: - * PCI_VENDOR_ID_IBM/PCI_VENDOR_ID_LENOVO */ - - char *bios_version_str; /* Something like 1ZET51WW (1.03z) */ - char *ec_version_str; /* Something like 1ZHT51WW-1.04a */ - - u16 bios_model; /* Big Endian, TP-1Y = 0x5931, 0 = unknown */ - u16 ec_model; - - char *model_str; -}; -static struct thinkpad_id_data thinkpad_id; +#define __unused __attribute__ ((unused)) static enum { TPACPI_LIFE_INIT = 0, @@ -255,9 +123,6 @@ static enum { TPACPI_LIFE_EXITING, } tpacpi_lifecycle; -static int experimental; -static u32 dbg_level; - /**************************************************************************** **************************************************************************** * @@ -272,13 +137,13 @@ static u32 dbg_level; static acpi_handle root_handle; -#define TPACPI_HANDLE(object, parent, paths...) \ +#define IBM_HANDLE(object, parent, paths...) \ static acpi_handle object##_handle; \ static acpi_handle *object##_parent = &parent##_handle; \ static char *object##_path; \ static char *object##_paths[] = { paths } -TPACPI_HANDLE(ec, root, "\\_SB.PCI0.ISA.EC0", /* 240, 240x */ +IBM_HANDLE(ec, root, "\\_SB.PCI0.ISA.EC0", /* 240, 240x */ "\\_SB.PCI.ISA.EC", /* 570 */ "\\_SB.PCI0.ISA0.EC0", /* 600e/x, 770e, 770x */ "\\_SB.PCI0.ISA.EC", /* A21e, A2xm/p, T20-22, X20-21 */ @@ -287,16 +152,20 @@ TPACPI_HANDLE(ec, root, "\\_SB.PCI0.ISA.EC0", /* 240, 240x */ "\\_SB.PCI0.LPC.EC", /* all others */ ); -TPACPI_HANDLE(ecrd, ec, "ECRD"); /* 570 */ -TPACPI_HANDLE(ecwr, ec, "ECWR"); /* 570 */ +IBM_HANDLE(ecrd, ec, "ECRD"); /* 570 */ +IBM_HANDLE(ecwr, ec, "ECWR"); /* 570 */ + -TPACPI_HANDLE(cmos, root, "\\UCMS", /* R50, R50e, R50p, R51, */ - /* T4x, X31, X40 */ +/************************************************************************* + * Misc ACPI handles + */ + +IBM_HANDLE(cmos, root, "\\UCMS", /* R50, R50e, R50p, R51, T4x, X31, X40 */ "\\CMOS", /* A3x, G4x, R32, T23, T30, X22-24, X30 */ "\\CMS", /* R40, R40e */ ); /* all others */ -TPACPI_HANDLE(hkey, ec, "\\_SB.HKEY", /* 600e/x, 770e, 770x */ +IBM_HANDLE(hkey, ec, "\\_SB.HKEY", /* 600e/x, 770e, 770x */ "^HKEY", /* R30, R31 */ "HKEY", /* all others */ ); /* 570 */ @@ -311,7 +180,7 @@ static int acpi_evalf(acpi_handle handle, { char *fmt0 = fmt; struct acpi_object_list params; - union acpi_object in_objs[TPACPI_MAX_ACPI_ARGS]; + union acpi_object in_objs[IBM_MAX_ACPI_ARGS]; struct acpi_buffer result, *resultp; union acpi_object out_obj; acpi_status status; @@ -321,7 +190,7 @@ static int acpi_evalf(acpi_handle handle, int quiet; if (!*fmt) { - printk(TPACPI_ERR "acpi_evalf() called with empty format\n"); + printk(IBM_ERR "acpi_evalf() called with empty format\n"); return 0; } @@ -346,7 +215,7 @@ static int acpi_evalf(acpi_handle handle, break; /* add more types as needed */ default: - printk(TPACPI_ERR "acpi_evalf() called " + printk(IBM_ERR "acpi_evalf() called " "with invalid format character '%c'\n", c); return 0; } @@ -373,19 +242,29 @@ static int acpi_evalf(acpi_handle handle, break; /* add more types as needed */ default: - printk(TPACPI_ERR "acpi_evalf() called " + printk(IBM_ERR "acpi_evalf() called " "with invalid format character '%c'\n", res_type); return 0; } if (!success && !quiet) - printk(TPACPI_ERR "acpi_evalf(%s, %s, ...) failed: %d\n", + printk(IBM_ERR "acpi_evalf(%s, %s, ...) failed: %d\n", method, fmt0, status); return success; } -static int acpi_ec_read(int i, u8 *p) +static void __unused acpi_print_int(acpi_handle handle, char *method) +{ + int i; + + if (acpi_evalf(handle, &i, method, "d")) + printk(IBM_INFO "%s = 0x%x\n", method, i); + else + printk(IBM_ERR "error calling %s\n", method); +} + +static int acpi_ec_read(int i, u8 * p) { int v; @@ -414,7 +293,6 @@ static int acpi_ec_write(int i, u8 v) return 1; } -#if defined(CONFIG_THINKPAD_ACPI_DOCK) || defined(CONFIG_THINKPAD_ACPI_BAY) static int _sta(acpi_handle handle) { int status; @@ -424,7 +302,6 @@ static int _sta(acpi_handle handle) return status; } -#endif static int issue_thinkpad_cmos_command(int cmos_cmd) { @@ -441,10 +318,6 @@ static int issue_thinkpad_cmos_command(int cmos_cmd) * ACPI device model */ -#define TPACPI_ACPIHANDLE_INIT(object) \ - drv_acpi_handle_init(#object, &object##_handle, *object##_parent, \ - object##_paths, ARRAY_SIZE(object##_paths), &object##_path) - static void drv_acpi_handle_init(char *name, acpi_handle *handle, acpi_handle parent, char **paths, int num_paths, char **path) @@ -499,27 +372,25 @@ static int __init setup_acpi_notify(struct ibm_struct *ibm) rc = acpi_bus_get_device(*ibm->acpi->handle, &ibm->acpi->device); if (rc < 0) { - printk(TPACPI_ERR "acpi_bus_get_device(%s) failed: %d\n", + printk(IBM_ERR "acpi_bus_get_device(%s) failed: %d\n", ibm->name, rc); return -ENODEV; } acpi_driver_data(ibm->acpi->device) = ibm; sprintf(acpi_device_class(ibm->acpi->device), "%s/%s", - TPACPI_ACPI_EVENT_PREFIX, + IBM_ACPI_EVENT_PREFIX, ibm->name); status = acpi_install_notify_handler(*ibm->acpi->handle, ibm->acpi->type, dispatch_acpi_notify, ibm); if (ACPI_FAILURE(status)) { if (status == AE_ALREADY_EXISTS) { - printk(TPACPI_NOTICE - "another device driver is already " - "handling %s events\n", ibm->name); + printk(IBM_NOTICE "another device driver is already handling %s events\n", + ibm->name); } else { - printk(TPACPI_ERR - "acpi_install_notify_handler(%s) failed: %d\n", - ibm->name, status); + printk(IBM_ERR "acpi_install_notify_handler(%s) failed: %d\n", + ibm->name, status); } return -ENODEV; } @@ -543,18 +414,18 @@ static int __init register_tpacpi_subdriver(struct ibm_struct *ibm) ibm->acpi->driver = kzalloc(sizeof(struct acpi_driver), GFP_KERNEL); if (!ibm->acpi->driver) { - printk(TPACPI_ERR "kzalloc(ibm->driver) failed\n"); + printk(IBM_ERR "kzalloc(ibm->driver) failed\n"); return -ENOMEM; } - sprintf(ibm->acpi->driver->name, "%s_%s", TPACPI_NAME, ibm->name); + sprintf(ibm->acpi->driver->name, "%s_%s", IBM_NAME, ibm->name); ibm->acpi->driver->ids = ibm->acpi->hid; ibm->acpi->driver->ops.add = &tpacpi_device_add; rc = acpi_bus_register_driver(ibm->acpi->driver); if (rc < 0) { - printk(TPACPI_ERR "acpi_bus_register_driver(%s) failed: %d\n", + printk(IBM_ERR "acpi_bus_register_driver(%s) failed: %d\n", ibm->name, rc); kfree(ibm->acpi->driver); ibm->acpi->driver = NULL; @@ -599,7 +470,7 @@ static int dispatch_procfs_read(char *page, char **start, off_t off, } static int dispatch_procfs_write(struct file *file, - const char __user *userbuf, + const char __user * userbuf, unsigned long count, void *data) { struct ibm_struct *ibm = data; @@ -659,22 +530,7 @@ static struct platform_device *tpacpi_sensors_pdev; static struct device *tpacpi_hwmon; static struct input_dev *tpacpi_inputdev; static struct mutex tpacpi_inputdev_send_mutex; -static LIST_HEAD(tpacpi_all_drivers); - -static int tpacpi_suspend_handler(struct platform_device *pdev, - pm_message_t state) -{ - struct ibm_struct *ibm, *itmp; - - list_for_each_entry_safe(ibm, itmp, - &tpacpi_all_drivers, - all_drivers) { - if (ibm->suspend) - (ibm->suspend)(state); - } - return 0; -} static int tpacpi_resume_handler(struct platform_device *pdev) { @@ -692,36 +548,107 @@ static int tpacpi_resume_handler(struct platform_device *pdev) static struct platform_driver tpacpi_pdriver = { .driver = { - .name = TPACPI_DRVR_NAME, + .name = IBM_DRVR_NAME, .owner = THIS_MODULE, }, - .suspend = tpacpi_suspend_handler, .resume = tpacpi_resume_handler, }; static struct platform_driver tpacpi_hwmon_pdriver = { .driver = { - .name = TPACPI_HWMON_DRVR_NAME, + .name = IBM_HWMON_DRVR_NAME, .owner = THIS_MODULE, }, }; /************************************************************************* - * sysfs support helpers + * thinkpad-acpi driver attributes */ -struct attribute_set { - unsigned int members, max_members; - struct attribute_group group; +/* interface_version --------------------------------------------------- */ +static ssize_t tpacpi_driver_interface_version_show( + struct device_driver *drv, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "0x%08x\n", TPACPI_SYSFS_VERSION); +} + +static DRIVER_ATTR(interface_version, S_IRUGO, + tpacpi_driver_interface_version_show, NULL); + +/* debug_level --------------------------------------------------------- */ +static ssize_t tpacpi_driver_debug_show(struct device_driver *drv, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "0x%04x\n", dbg_level); +} + +static ssize_t tpacpi_driver_debug_store(struct device_driver *drv, + const char *buf, size_t count) +{ + unsigned long t; + + if (parse_strtoul(buf, 0xffff, &t)) + return -EINVAL; + + dbg_level = t; + + return count; +} + +static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO, + tpacpi_driver_debug_show, tpacpi_driver_debug_store); + +/* version ------------------------------------------------------------- */ +static ssize_t tpacpi_driver_version_show(struct device_driver *drv, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%s v%s\n", IBM_DESC, IBM_VERSION); +} + +static DRIVER_ATTR(version, S_IRUGO, + tpacpi_driver_version_show, NULL); + +/* --------------------------------------------------------------------- */ + +static struct driver_attribute* tpacpi_driver_attributes[] = { + &driver_attr_debug_level, &driver_attr_version, + &driver_attr_interface_version, }; +static int __init tpacpi_create_driver_attributes(struct device_driver *drv) +{ + int i, res; + + i = 0; + res = 0; + while (!res && i < ARRAY_SIZE(tpacpi_driver_attributes)) { + res = driver_create_file(drv, tpacpi_driver_attributes[i]); + i++; + } + + return res; +} + +static void tpacpi_remove_driver_attributes(struct device_driver *drv) +{ + int i; + + for(i = 0; i < ARRAY_SIZE(tpacpi_driver_attributes); i++) + driver_remove_file(drv, tpacpi_driver_attributes[i]); +} + +/************************************************************************* + * sysfs support helpers + */ + struct attribute_set_obj { struct attribute_set s; struct attribute *a; } __attribute__((packed)); static struct attribute_set *create_attr_set(unsigned int max_members, - const char *name) + const char* name) { struct attribute_set_obj *sobj; @@ -741,11 +668,8 @@ static struct attribute_set *create_attr_set(unsigned int max_members, return &sobj->s; } -#define destroy_attr_set(_set) \ - kfree(_set); - /* not multi-threaded safe, use it in a single thread per set */ -static int add_to_attr_set(struct attribute_set *s, struct attribute *attr) +static int add_to_attr_set(struct attribute_set* s, struct attribute *attr) { if (!s || !attr) return -EINVAL; @@ -759,7 +683,7 @@ static int add_to_attr_set(struct attribute_set *s, struct attribute *attr) return 0; } -static int add_many_to_attr_set(struct attribute_set *s, +static int add_many_to_attr_set(struct attribute_set* s, struct attribute **attr, unsigned int count) { @@ -774,15 +698,12 @@ static int add_many_to_attr_set(struct attribute_set *s, return 0; } -static void delete_attr_set(struct attribute_set *s, struct kobject *kobj) +static void delete_attr_set(struct attribute_set* s, struct kobject *kobj) { sysfs_remove_group(kobj, &s->group); destroy_attr_set(s); } -#define register_attr_set_with_sysfs(_attr_set, _kobj) \ - sysfs_create_group(_kobj, &_attr_set->group) - static int parse_strtoul(const char *buf, unsigned long max, unsigned long *value) { @@ -799,84 +720,6 @@ static int parse_strtoul(const char *buf, return 0; } -/************************************************************************* - * thinkpad-acpi driver attributes - */ - -/* interface_version --------------------------------------------------- */ -static ssize_t tpacpi_driver_interface_version_show( - struct device_driver *drv, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "0x%08x\n", TPACPI_SYSFS_VERSION); -} - -static DRIVER_ATTR(interface_version, S_IRUGO, - tpacpi_driver_interface_version_show, NULL); - -/* debug_level --------------------------------------------------------- */ -static ssize_t tpacpi_driver_debug_show(struct device_driver *drv, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "0x%04x\n", dbg_level); -} - -static ssize_t tpacpi_driver_debug_store(struct device_driver *drv, - const char *buf, size_t count) -{ - unsigned long t; - - if (parse_strtoul(buf, 0xffff, &t)) - return -EINVAL; - - dbg_level = t; - - return count; -} - -static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO, - tpacpi_driver_debug_show, tpacpi_driver_debug_store); - -/* version ------------------------------------------------------------- */ -static ssize_t tpacpi_driver_version_show(struct device_driver *drv, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%s v%s\n", - TPACPI_DESC, TPACPI_VERSION); -} - -static DRIVER_ATTR(version, S_IRUGO, - tpacpi_driver_version_show, NULL); - -/* --------------------------------------------------------------------- */ - -static struct driver_attribute *tpacpi_driver_attributes[] = { - &driver_attr_debug_level, &driver_attr_version, - &driver_attr_interface_version, -}; - -static int __init tpacpi_create_driver_attributes(struct device_driver *drv) -{ - int i, res; - - i = 0; - res = 0; - while (!res && i < ARRAY_SIZE(tpacpi_driver_attributes)) { - res = driver_create_file(drv, tpacpi_driver_attributes[i]); - i++; - } - - return res; -} - -static void tpacpi_remove_driver_attributes(struct device_driver *drv) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(tpacpi_driver_attributes); i++) - driver_remove_file(drv, tpacpi_driver_attributes[i]); -} - /**************************************************************************** **************************************************************************** * @@ -891,17 +734,17 @@ static void tpacpi_remove_driver_attributes(struct device_driver *drv) static int __init thinkpad_acpi_driver_init(struct ibm_init_struct *iibm) { - printk(TPACPI_INFO "%s v%s\n", TPACPI_DESC, TPACPI_VERSION); - printk(TPACPI_INFO "%s\n", TPACPI_URL); + printk(IBM_INFO "%s v%s\n", IBM_DESC, IBM_VERSION); + printk(IBM_INFO "%s\n", IBM_URL); - printk(TPACPI_INFO "ThinkPad BIOS %s, EC %s\n", + printk(IBM_INFO "ThinkPad BIOS %s, EC %s\n", (thinkpad_id.bios_version_str) ? thinkpad_id.bios_version_str : "unknown", (thinkpad_id.ec_version_str) ? thinkpad_id.ec_version_str : "unknown"); if (thinkpad_id.vendor && thinkpad_id.model_str) - printk(TPACPI_INFO "%s %s\n", + printk(IBM_INFO "%s %s\n", (thinkpad_id.vendor == PCI_VENDOR_ID_IBM) ? "IBM" : ((thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) ? @@ -915,8 +758,8 @@ static int thinkpad_acpi_driver_read(char *p) { int len = 0; - len += sprintf(p + len, "driver:\t\t%s\n", TPACPI_DESC); - len += sprintf(p + len, "version:\t%s\n", TPACPI_VERSION); + len += sprintf(p + len, "driver:\t\t%s\n", IBM_DESC); + len += sprintf(p + len, "version:\t%s\n", IBM_VERSION); return len; } @@ -930,129 +773,15 @@ static struct ibm_struct thinkpad_acpi_driver_data = { * Hotkey subdriver */ -enum { /* hot key scan codes (derived from ACPI DSDT) */ - TP_ACPI_HOTKEYSCAN_FNF1 = 0, - TP_ACPI_HOTKEYSCAN_FNF2, - TP_ACPI_HOTKEYSCAN_FNF3, - TP_ACPI_HOTKEYSCAN_FNF4, - TP_ACPI_HOTKEYSCAN_FNF5, - TP_ACPI_HOTKEYSCAN_FNF6, - TP_ACPI_HOTKEYSCAN_FNF7, - TP_ACPI_HOTKEYSCAN_FNF8, - TP_ACPI_HOTKEYSCAN_FNF9, - TP_ACPI_HOTKEYSCAN_FNF10, - TP_ACPI_HOTKEYSCAN_FNF11, - TP_ACPI_HOTKEYSCAN_FNF12, - TP_ACPI_HOTKEYSCAN_FNBACKSPACE, - TP_ACPI_HOTKEYSCAN_FNINSERT, - TP_ACPI_HOTKEYSCAN_FNDELETE, - TP_ACPI_HOTKEYSCAN_FNHOME, - TP_ACPI_HOTKEYSCAN_FNEND, - TP_ACPI_HOTKEYSCAN_FNPAGEUP, - TP_ACPI_HOTKEYSCAN_FNPAGEDOWN, - TP_ACPI_HOTKEYSCAN_FNSPACE, - TP_ACPI_HOTKEYSCAN_VOLUMEUP, - TP_ACPI_HOTKEYSCAN_VOLUMEDOWN, - TP_ACPI_HOTKEYSCAN_MUTE, - TP_ACPI_HOTKEYSCAN_THINKPAD, -}; - -enum { /* Keys available through NVRAM polling */ - TPACPI_HKEY_NVRAM_KNOWN_MASK = 0x00fb88c0U, - TPACPI_HKEY_NVRAM_GOOD_MASK = 0x00fb8000U, -}; - -enum { /* Positions of some of the keys in hotkey masks */ - TP_ACPI_HKEY_DISPSWTCH_MASK = 1 << TP_ACPI_HOTKEYSCAN_FNF7, - TP_ACPI_HKEY_DISPXPAND_MASK = 1 << TP_ACPI_HOTKEYSCAN_FNF8, - TP_ACPI_HKEY_HIBERNATE_MASK = 1 << TP_ACPI_HOTKEYSCAN_FNF12, - TP_ACPI_HKEY_BRGHTUP_MASK = 1 << TP_ACPI_HOTKEYSCAN_FNHOME, - TP_ACPI_HKEY_BRGHTDWN_MASK = 1 << TP_ACPI_HOTKEYSCAN_FNEND, - TP_ACPI_HKEY_THNKLGHT_MASK = 1 << TP_ACPI_HOTKEYSCAN_FNPAGEUP, - TP_ACPI_HKEY_ZOOM_MASK = 1 << TP_ACPI_HOTKEYSCAN_FNSPACE, - TP_ACPI_HKEY_VOLUP_MASK = 1 << TP_ACPI_HOTKEYSCAN_VOLUMEUP, - TP_ACPI_HKEY_VOLDWN_MASK = 1 << TP_ACPI_HOTKEYSCAN_VOLUMEDOWN, - TP_ACPI_HKEY_MUTE_MASK = 1 << TP_ACPI_HOTKEYSCAN_MUTE, - TP_ACPI_HKEY_THINKPAD_MASK = 1 << TP_ACPI_HOTKEYSCAN_THINKPAD, -}; - -enum { /* NVRAM to ACPI HKEY group map */ - TP_NVRAM_HKEY_GROUP_HK2 = TP_ACPI_HKEY_THINKPAD_MASK | - TP_ACPI_HKEY_ZOOM_MASK | - TP_ACPI_HKEY_DISPSWTCH_MASK | - TP_ACPI_HKEY_HIBERNATE_MASK, - TP_NVRAM_HKEY_GROUP_BRIGHTNESS = TP_ACPI_HKEY_BRGHTUP_MASK | - TP_ACPI_HKEY_BRGHTDWN_MASK, - TP_NVRAM_HKEY_GROUP_VOLUME = TP_ACPI_HKEY_VOLUP_MASK | - TP_ACPI_HKEY_VOLDWN_MASK | - TP_ACPI_HKEY_MUTE_MASK, -}; - -#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL -struct tp_nvram_state { - u16 thinkpad_toggle:1; - u16 zoom_toggle:1; - u16 display_toggle:1; - u16 thinklight_toggle:1; - u16 hibernate_toggle:1; - u16 displayexp_toggle:1; - u16 display_state:1; - u16 brightness_toggle:1; - u16 volume_toggle:1; - u16 mute:1; - - u8 brightness_level; - u8 volume_level; -}; - -static struct task_struct *tpacpi_hotkey_task; -static u32 hotkey_source_mask; /* bit mask 0=ACPI,1=NVRAM */ -static int hotkey_poll_freq = 10; /* Hz */ -static struct mutex hotkey_thread_mutex; -static struct mutex hotkey_thread_data_mutex; -static unsigned int hotkey_config_change; - -#else /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ - -#define hotkey_source_mask 0U - -#endif /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ - -static struct mutex hotkey_mutex; - -static enum { /* Reasons for waking up */ - TP_ACPI_WAKEUP_NONE = 0, /* None or unknown */ - TP_ACPI_WAKEUP_BAYEJ, /* Bay ejection request */ - TP_ACPI_WAKEUP_UNDOCK, /* Undock request */ -} hotkey_wakeup_reason; - -static int hotkey_autosleep_ack; - static int hotkey_orig_status; static u32 hotkey_orig_mask; static u32 hotkey_all_mask; static u32 hotkey_reserved_mask; -static u32 hotkey_mask; - -static unsigned int hotkey_report_mode; static u16 *hotkey_keycode_map; static struct attribute_set *hotkey_dev_attributes; -#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL -#define HOTKEY_CONFIG_CRITICAL_START \ - do { \ - mutex_lock(&hotkey_thread_data_mutex); \ - hotkey_config_change++; \ - } while (0); -#define HOTKEY_CONFIG_CRITICAL_END \ - mutex_unlock(&hotkey_thread_data_mutex); -#else -#define HOTKEY_CONFIG_CRITICAL_START -#define HOTKEY_CONFIG_CRITICAL_END -#endif /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ - static int hotkey_get_wlsw(int *status) { if (!acpi_evalf(hkey_handle, status, "WLSW", "d")) @@ -1060,400 +789,15 @@ static int hotkey_get_wlsw(int *status) return 0; } -/* - * Call with hotkey_mutex held - */ -static int hotkey_mask_get(void) -{ - u32 m = 0; - - if (tp_features.hotkey_mask) { - if (!acpi_evalf(hkey_handle, &m, "DHKN", "d")) - return -EIO; - } - hotkey_mask = m | (hotkey_source_mask & hotkey_mask); - - return 0; -} - -/* - * Call with hotkey_mutex held - */ -static int hotkey_mask_set(u32 mask) -{ - int i; - int rc = 0; - - if (tp_features.hotkey_mask) { - HOTKEY_CONFIG_CRITICAL_START - for (i = 0; i < 32; i++) { - u32 m = 1 << i; - /* enable in firmware mask only keys not in NVRAM - * mode, but enable the key in the cached hotkey_mask - * regardless of mode, or the key will end up - * disabled by hotkey_mask_get() */ - if (!acpi_evalf(hkey_handle, - NULL, "MHKM", "vdd", i + 1, - !!((mask & ~hotkey_source_mask) & m))) { - rc = -EIO; - break; - } else { - hotkey_mask = (hotkey_mask & ~m) | (mask & m); - } - } - HOTKEY_CONFIG_CRITICAL_END - - /* hotkey_mask_get must be called unconditionally below */ - if (!hotkey_mask_get() && !rc && - (hotkey_mask & ~hotkey_source_mask) != - (mask & ~hotkey_source_mask)) { - printk(TPACPI_NOTICE - "requested hot key mask 0x%08x, but " - "firmware forced it to 0x%08x\n", - mask, hotkey_mask); - } - } else { -#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL - HOTKEY_CONFIG_CRITICAL_START - hotkey_mask = mask & hotkey_source_mask; - HOTKEY_CONFIG_CRITICAL_END - hotkey_mask_get(); - if (hotkey_mask != mask) { - printk(TPACPI_NOTICE - "requested hot key mask 0x%08x, " - "forced to 0x%08x (NVRAM poll mask is " - "0x%08x): no firmware mask support\n", - mask, hotkey_mask, hotkey_source_mask); - } -#else - hotkey_mask_get(); - rc = -ENXIO; -#endif /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ - } - - return rc; -} - -static int hotkey_status_get(int *status) -{ - if (!acpi_evalf(hkey_handle, status, "DHKC", "d")) - return -EIO; - - return 0; -} - -static int hotkey_status_set(int status) -{ - if (!acpi_evalf(hkey_handle, NULL, "MHKC", "vd", status)) - return -EIO; - - return 0; -} - -static void tpacpi_input_send_radiosw(void) -{ - int wlsw; - - mutex_lock(&tpacpi_inputdev_send_mutex); - - if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw)) { - input_report_switch(tpacpi_inputdev, - SW_RADIO, !!wlsw); - input_sync(tpacpi_inputdev); - } - - mutex_unlock(&tpacpi_inputdev_send_mutex); -} - -static void tpacpi_input_send_key(unsigned int scancode) -{ - unsigned int keycode; - - keycode = hotkey_keycode_map[scancode]; - - if (keycode != KEY_RESERVED) { - mutex_lock(&tpacpi_inputdev_send_mutex); - - input_report_key(tpacpi_inputdev, keycode, 1); - if (keycode == KEY_UNKNOWN) - input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN, - scancode); - input_sync(tpacpi_inputdev); - - input_report_key(tpacpi_inputdev, keycode, 0); - if (keycode == KEY_UNKNOWN) - input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN, - scancode); - input_sync(tpacpi_inputdev); - - mutex_unlock(&tpacpi_inputdev_send_mutex); - } -} - -#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL -static struct tp_acpi_drv_struct ibm_hotkey_acpidriver; - -static void tpacpi_hotkey_send_key(unsigned int scancode) -{ - tpacpi_input_send_key(scancode); - if (hotkey_report_mode < 2) { - acpi_bus_generate_proc_event(ibm_hotkey_acpidriver.device, - 0x80, 0x1001 + scancode); - } -} - -static void hotkey_read_nvram(struct tp_nvram_state *n, u32 m) -{ - u8 d; - - if (m & TP_NVRAM_HKEY_GROUP_HK2) { - d = nvram_read_byte(TP_NVRAM_ADDR_HK2); - n->thinkpad_toggle = !!(d & TP_NVRAM_MASK_HKT_THINKPAD); - n->zoom_toggle = !!(d & TP_NVRAM_MASK_HKT_ZOOM); - n->display_toggle = !!(d & TP_NVRAM_MASK_HKT_DISPLAY); - n->hibernate_toggle = !!(d & TP_NVRAM_MASK_HKT_HIBERNATE); - } - if (m & TP_ACPI_HKEY_THNKLGHT_MASK) { - d = nvram_read_byte(TP_NVRAM_ADDR_THINKLIGHT); - n->thinklight_toggle = !!(d & TP_NVRAM_MASK_THINKLIGHT); - } - if (m & TP_ACPI_HKEY_DISPXPAND_MASK) { - d = nvram_read_byte(TP_NVRAM_ADDR_VIDEO); - n->displayexp_toggle = - !!(d & TP_NVRAM_MASK_HKT_DISPEXPND); - } - if (m & TP_NVRAM_HKEY_GROUP_BRIGHTNESS) { - d = nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS); - n->brightness_level = (d & TP_NVRAM_MASK_LEVEL_BRIGHTNESS) - >> TP_NVRAM_POS_LEVEL_BRIGHTNESS; - n->brightness_toggle = - !!(d & TP_NVRAM_MASK_HKT_BRIGHTNESS); - } - if (m & TP_NVRAM_HKEY_GROUP_VOLUME) { - d = nvram_read_byte(TP_NVRAM_ADDR_MIXER); - n->volume_level = (d & TP_NVRAM_MASK_LEVEL_VOLUME) - >> TP_NVRAM_POS_LEVEL_VOLUME; - n->mute = !!(d & TP_NVRAM_MASK_MUTE); - n->volume_toggle = !!(d & TP_NVRAM_MASK_HKT_VOLUME); - } -} - -#define TPACPI_COMPARE_KEY(__scancode, __member) \ - do { \ - if ((mask & (1 << __scancode)) && \ - oldn->__member != newn->__member) \ - tpacpi_hotkey_send_key(__scancode); \ - } while (0) - -#define TPACPI_MAY_SEND_KEY(__scancode) \ - do { if (mask & (1 << __scancode)) \ - tpacpi_hotkey_send_key(__scancode); } while (0) - -static void hotkey_compare_and_issue_event(struct tp_nvram_state *oldn, - struct tp_nvram_state *newn, - u32 mask) -{ - TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_THINKPAD, thinkpad_toggle); - TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_FNSPACE, zoom_toggle); - TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_FNF7, display_toggle); - TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_FNF12, hibernate_toggle); - - TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_FNPAGEUP, thinklight_toggle); - - TPACPI_COMPARE_KEY(TP_ACPI_HOTKEYSCAN_FNF8, displayexp_toggle); - - /* handle volume */ - if (oldn->volume_toggle != newn->volume_toggle) { - if (oldn->mute != newn->mute) { - TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_MUTE); - } - if (oldn->volume_level > newn->volume_level) { - TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEDOWN); - } else if (oldn->volume_level < newn->volume_level) { - TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEUP); - } else if (oldn->mute == newn->mute) { - /* repeated key presses that didn't change state */ - if (newn->mute) { - TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_MUTE); - } else if (newn->volume_level != 0) { - TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEUP); - } else { - TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_VOLUMEDOWN); - } - } - } - - /* handle brightness */ - if (oldn->brightness_toggle != newn->brightness_toggle) { - if (oldn->brightness_level < newn->brightness_level) { - TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_FNHOME); - } else if (oldn->brightness_level > newn->brightness_level) { - TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_FNEND); - } else { - /* repeated key presses that didn't change state */ - if (newn->brightness_level != 0) { - TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_FNHOME); - } else { - TPACPI_MAY_SEND_KEY(TP_ACPI_HOTKEYSCAN_FNEND); - } - } - } -} - -#undef TPACPI_COMPARE_KEY -#undef TPACPI_MAY_SEND_KEY - -static int hotkey_kthread(void *data) -{ - struct tp_nvram_state s[2]; - u32 mask; - unsigned int si, so; - unsigned long t; - unsigned int change_detector, must_reset; - - mutex_lock(&hotkey_thread_mutex); - - if (tpacpi_lifecycle == TPACPI_LIFE_EXITING) - goto exit; - - set_freezable(); - - so = 0; - si = 1; - t = 0; - - /* Initial state for compares */ - mutex_lock(&hotkey_thread_data_mutex); - change_detector = hotkey_config_change; - mask = hotkey_source_mask & hotkey_mask; - mutex_unlock(&hotkey_thread_data_mutex); - hotkey_read_nvram(&s[so], mask); - - while (!kthread_should_stop() && hotkey_poll_freq) { - if (t == 0) - t = 1000/hotkey_poll_freq; - t = msleep_interruptible(t); - if (unlikely(kthread_should_stop())) - break; - must_reset = try_to_freeze(); - if (t > 0 && !must_reset) - continue; - - mutex_lock(&hotkey_thread_data_mutex); - if (must_reset || hotkey_config_change != change_detector) { - /* forget old state on thaw or config change */ - si = so; - t = 0; - change_detector = hotkey_config_change; - } - mask = hotkey_source_mask & hotkey_mask; - mutex_unlock(&hotkey_thread_data_mutex); - - if (likely(mask)) { - hotkey_read_nvram(&s[si], mask); - if (likely(si != so)) { - hotkey_compare_and_issue_event(&s[so], &s[si], - mask); - } - } - - so = si; - si ^= 1; - } - -exit: - mutex_unlock(&hotkey_thread_mutex); - return 0; -} - -static void hotkey_poll_stop_sync(void) -{ - if (tpacpi_hotkey_task) { - if (frozen(tpacpi_hotkey_task) || - freezing(tpacpi_hotkey_task)) - thaw_process(tpacpi_hotkey_task); - - kthread_stop(tpacpi_hotkey_task); - tpacpi_hotkey_task = NULL; - mutex_lock(&hotkey_thread_mutex); - /* at this point, the thread did exit */ - mutex_unlock(&hotkey_thread_mutex); - } -} - -/* call with hotkey_mutex held */ -static void hotkey_poll_setup(int may_warn) -{ - if ((hotkey_source_mask & hotkey_mask) != 0 && - hotkey_poll_freq > 0 && - (tpacpi_inputdev->users > 0 || hotkey_report_mode < 2)) { - if (!tpacpi_hotkey_task) { - tpacpi_hotkey_task = kthread_run(hotkey_kthread, - NULL, - TPACPI_FILE "d"); - if (IS_ERR(tpacpi_hotkey_task)) { - tpacpi_hotkey_task = NULL; - printk(TPACPI_ERR - "could not create kernel thread " - "for hotkey polling\n"); - } - } - } else { - hotkey_poll_stop_sync(); - if (may_warn && - hotkey_source_mask != 0 && hotkey_poll_freq == 0) { - printk(TPACPI_NOTICE - "hot keys 0x%08x require polling, " - "which is currently disabled\n", - hotkey_source_mask); - } - } -} - -static void hotkey_poll_setup_safe(int may_warn) -{ - mutex_lock(&hotkey_mutex); - hotkey_poll_setup(may_warn); - mutex_unlock(&hotkey_mutex); -} - -static int hotkey_inputdev_open(struct input_dev *dev) -{ - switch (tpacpi_lifecycle) { - case TPACPI_LIFE_INIT: - /* - * hotkey_init will call hotkey_poll_setup_safe - * at the appropriate moment - */ - return 0; - case TPACPI_LIFE_EXITING: - return -EBUSY; - case TPACPI_LIFE_RUNNING: - hotkey_poll_setup_safe(0); - return 0; - } - - /* Should only happen if tpacpi_lifecycle is corrupt */ - BUG(); - return -EBUSY; -} - -static void hotkey_inputdev_close(struct input_dev *dev) -{ - /* disable hotkey polling when possible */ - if (tpacpi_lifecycle == TPACPI_LIFE_RUNNING) - hotkey_poll_setup_safe(0); -} -#endif /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ - -/* sysfs hotkey enable ------------------------------------------------- */ -static ssize_t hotkey_enable_show(struct device *dev, - struct device_attribute *attr, - char *buf) +/* sysfs hotkey enable ------------------------------------------------- */ +static ssize_t hotkey_enable_show(struct device *dev, + struct device_attribute *attr, + char *buf) { int res, status; + u32 mask; - res = hotkey_status_get(&status); + res = hotkey_get(&status, &mask); if (res) return res; @@ -1465,12 +809,15 @@ static ssize_t hotkey_enable_store(struct device *dev, const char *buf, size_t count) { unsigned long t; - int res; + int res, status; + u32 mask; if (parse_strtoul(buf, 1, &t)) return -EINVAL; - res = hotkey_status_set(t); + res = hotkey_get(&status, &mask); + if (!res) + res = hotkey_set(t, mask); return (res) ? res : count; } @@ -1484,15 +831,14 @@ static ssize_t hotkey_mask_show(struct device *dev, struct device_attribute *attr, char *buf) { - int res; + int res, status; + u32 mask; - if (mutex_lock_interruptible(&hotkey_mutex)) - return -ERESTARTSYS; - res = hotkey_mask_get(); - mutex_unlock(&hotkey_mutex); + res = hotkey_get(&status, &mask); + if (res) + return res; - return (res)? - res : snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_mask); + return snprintf(buf, PAGE_SIZE, "0x%08x\n", mask); } static ssize_t hotkey_mask_store(struct device *dev, @@ -1500,21 +846,15 @@ static ssize_t hotkey_mask_store(struct device *dev, const char *buf, size_t count) { unsigned long t; - int res; + int res, status; + u32 mask; if (parse_strtoul(buf, 0xffffffffUL, &t)) return -EINVAL; - if (mutex_lock_interruptible(&hotkey_mutex)) - return -ERESTARTSYS; - - res = hotkey_mask_set(t); - -#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL - hotkey_poll_setup(1); -#endif - - mutex_unlock(&hotkey_mutex); + res = hotkey_get(&status, &mask); + if (!res) + hotkey_set(status, t); return (res) ? res : count; } @@ -1550,8 +890,7 @@ static ssize_t hotkey_all_mask_show(struct device *dev, struct device_attribute *attr, char *buf) { - return snprintf(buf, PAGE_SIZE, "0x%08x\n", - hotkey_all_mask | hotkey_source_mask); + return snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_all_mask); } static struct device_attribute dev_attr_hotkey_all_mask = @@ -1563,87 +902,14 @@ static ssize_t hotkey_recommended_mask_show(struct device *dev, char *buf) { return snprintf(buf, PAGE_SIZE, "0x%08x\n", - (hotkey_all_mask | hotkey_source_mask) - & ~hotkey_reserved_mask); + hotkey_all_mask & ~hotkey_reserved_mask); } static struct device_attribute dev_attr_hotkey_recommended_mask = __ATTR(hotkey_recommended_mask, S_IRUGO, hotkey_recommended_mask_show, NULL); -#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL - -/* sysfs hotkey hotkey_source_mask ------------------------------------- */ -static ssize_t hotkey_source_mask_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_source_mask); -} - -static ssize_t hotkey_source_mask_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned long t; - - if (parse_strtoul(buf, 0xffffffffUL, &t) || - ((t & ~TPACPI_HKEY_NVRAM_KNOWN_MASK) != 0)) - return -EINVAL; - - if (mutex_lock_interruptible(&hotkey_mutex)) - return -ERESTARTSYS; - - HOTKEY_CONFIG_CRITICAL_START - hotkey_source_mask = t; - HOTKEY_CONFIG_CRITICAL_END - - hotkey_poll_setup(1); - - mutex_unlock(&hotkey_mutex); - - return count; -} - -static struct device_attribute dev_attr_hotkey_source_mask = - __ATTR(hotkey_source_mask, S_IWUSR | S_IRUGO, - hotkey_source_mask_show, hotkey_source_mask_store); - -/* sysfs hotkey hotkey_poll_freq --------------------------------------- */ -static ssize_t hotkey_poll_freq_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", hotkey_poll_freq); -} - -static ssize_t hotkey_poll_freq_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned long t; - - if (parse_strtoul(buf, 25, &t)) - return -EINVAL; - - if (mutex_lock_interruptible(&hotkey_mutex)) - return -ERESTARTSYS; - - hotkey_poll_freq = t; - - hotkey_poll_setup(1); - mutex_unlock(&hotkey_mutex); - - return count; -} - -static struct device_attribute dev_attr_hotkey_poll_freq = - __ATTR(hotkey_poll_freq, S_IWUSR | S_IRUGO, - hotkey_poll_freq_show, hotkey_poll_freq_store); - -#endif /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ - -/* sysfs hotkey radio_sw (pollable) ------------------------------------ */ +/* sysfs hotkey radio_sw ----------------------------------------------- */ static ssize_t hotkey_radio_sw_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -1659,13 +925,6 @@ static ssize_t hotkey_radio_sw_show(struct device *dev, static struct device_attribute dev_attr_hotkey_radio_sw = __ATTR(hotkey_radio_sw, S_IRUGO, hotkey_radio_sw_show, NULL); -static void hotkey_radio_sw_notify_change(void) -{ - if (tp_features.hotkey_wlsw) - sysfs_notify(&tpacpi_pdev->dev.kobj, NULL, - "hotkey_radio_sw"); -} - /* sysfs hotkey report_mode -------------------------------------------- */ static ssize_t hotkey_report_mode_show(struct device *dev, struct device_attribute *attr, @@ -1678,132 +937,43 @@ static ssize_t hotkey_report_mode_show(struct device *dev, static struct device_attribute dev_attr_hotkey_report_mode = __ATTR(hotkey_report_mode, S_IRUGO, hotkey_report_mode_show, NULL); -/* sysfs wakeup reason (pollable) -------------------------------------- */ -static ssize_t hotkey_wakeup_reason_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", hotkey_wakeup_reason); -} +/* --------------------------------------------------------------------- */ -static struct device_attribute dev_attr_hotkey_wakeup_reason = - __ATTR(wakeup_reason, S_IRUGO, hotkey_wakeup_reason_show, NULL); - -void hotkey_wakeup_reason_notify_change(void) -{ - if (tp_features.hotkey_mask) - sysfs_notify(&tpacpi_pdev->dev.kobj, NULL, - "wakeup_reason"); -} - -/* sysfs wakeup hotunplug_complete (pollable) -------------------------- */ -static ssize_t hotkey_wakeup_hotunplug_complete_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", hotkey_autosleep_ack); -} - -static struct device_attribute dev_attr_hotkey_wakeup_hotunplug_complete = - __ATTR(wakeup_hotunplug_complete, S_IRUGO, - hotkey_wakeup_hotunplug_complete_show, NULL); - -void hotkey_wakeup_hotunplug_complete_notify_change(void) -{ - if (tp_features.hotkey_mask) - sysfs_notify(&tpacpi_pdev->dev.kobj, NULL, - "wakeup_hotunplug_complete"); -} - -/* --------------------------------------------------------------------- */ - -static struct attribute *hotkey_attributes[] __initdata = { - &dev_attr_hotkey_enable.attr, - &dev_attr_hotkey_bios_enabled.attr, - &dev_attr_hotkey_report_mode.attr, -#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL - &dev_attr_hotkey_mask.attr, - &dev_attr_hotkey_all_mask.attr, - &dev_attr_hotkey_recommended_mask.attr, - &dev_attr_hotkey_source_mask.attr, - &dev_attr_hotkey_poll_freq.attr, -#endif -}; +static struct attribute *hotkey_attributes[] __initdata = { + &dev_attr_hotkey_enable.attr, + &dev_attr_hotkey_report_mode.attr, +}; static struct attribute *hotkey_mask_attributes[] __initdata = { - &dev_attr_hotkey_bios_mask.attr, -#ifndef CONFIG_THINKPAD_ACPI_HOTKEY_POLL &dev_attr_hotkey_mask.attr, + &dev_attr_hotkey_bios_enabled.attr, + &dev_attr_hotkey_bios_mask.attr, &dev_attr_hotkey_all_mask.attr, &dev_attr_hotkey_recommended_mask.attr, -#endif - &dev_attr_hotkey_wakeup_reason.attr, - &dev_attr_hotkey_wakeup_hotunplug_complete.attr, }; static int __init hotkey_init(struct ibm_init_struct *iibm) { - /* Requirements for changing the default keymaps: - * - * 1. Many of the keys are mapped to KEY_RESERVED for very - * good reasons. Do not change them unless you have deep - * knowledge on the IBM and Lenovo ThinkPad firmware for - * the various ThinkPad models. The driver behaves - * differently for KEY_RESERVED: such keys have their - * hot key mask *unset* in mask_recommended, and also - * in the initial hot key mask programmed into the - * firmware at driver load time, which means the firm- - * ware may react very differently if you change them to - * something else; - * - * 2. You must be subscribed to the linux-thinkpad and - * ibm-acpi-devel mailing lists, and you should read the - * list archives since 2007 if you want to change the - * keymaps. This requirement exists so that you will - * know the past history of problems with the thinkpad- - * acpi driver keymaps, and also that you will be - * listening to any bug reports; - * - * 3. Do not send thinkpad-acpi specific patches directly to - * for merging, *ever*. Send them to the linux-acpi - * mailinglist for comments. Merging is to be done only - * through acpi-test and the ACPI maintainer. - * - * If the above is too much to ask, don't change the keymap. - * Ask the thinkpad-acpi maintainer to do it, instead. - */ + static u16 ibm_keycode_map[] __initdata = { /* Scan Codes 0x00 to 0x0B: ACPI HKEY FN+F1..F12 */ KEY_FN_F1, KEY_FN_F2, KEY_COFFEE, KEY_SLEEP, KEY_WLAN, KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8, KEY_FN_F9, KEY_FN_F10, KEY_FN_F11, KEY_SUSPEND, - - /* Scan codes 0x0C to 0x1F: Other ACPI HKEY hot keys */ + /* Scan codes 0x0C to 0x0F: Other ACPI HKEY hot keys */ KEY_UNKNOWN, /* 0x0C: FN+BACKSPACE */ KEY_UNKNOWN, /* 0x0D: FN+INSERT */ KEY_UNKNOWN, /* 0x0E: FN+DELETE */ - - /* brightness: firmware always reacts to them, unless - * X.org did some tricks in the radeon BIOS scratch - * registers of *some* models */ KEY_RESERVED, /* 0x0F: FN+HOME (brightness up) */ + /* Scan codes 0x10 to 0x1F: Extended ACPI HKEY hot keys */ KEY_RESERVED, /* 0x10: FN+END (brightness down) */ - - /* Thinklight: firmware always react to it */ KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */ - KEY_UNKNOWN, /* 0x12: FN+PGDOWN */ KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */ - - /* Volume: firmware always react to it and reprograms - * the built-in *extra* mixer. Never map it to control - * another mixer by default. */ KEY_RESERVED, /* 0x14: VOLUME UP */ KEY_RESERVED, /* 0x15: VOLUME DOWN */ KEY_RESERVED, /* 0x16: MUTE */ - KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */ - /* (assignments unknown, please report if found) */ KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, @@ -1813,37 +983,20 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) KEY_FN_F1, KEY_COFFEE, KEY_BATTERY, KEY_SLEEP, KEY_WLAN, KEY_FN_F6, KEY_SWITCHVIDEOMODE, KEY_FN_F8, KEY_FN_F9, KEY_FN_F10, KEY_FN_F11, KEY_SUSPEND, - - /* Scan codes 0x0C to 0x1F: Other ACPI HKEY hot keys */ + /* Scan codes 0x0C to 0x0F: Other ACPI HKEY hot keys */ KEY_UNKNOWN, /* 0x0C: FN+BACKSPACE */ KEY_UNKNOWN, /* 0x0D: FN+INSERT */ KEY_UNKNOWN, /* 0x0E: FN+DELETE */ - KEY_RESERVED, /* 0x0F: FN+HOME (brightness up) */ + /* Scan codes 0x10 to 0x1F: Extended ACPI HKEY hot keys */ KEY_RESERVED, /* 0x10: FN+END (brightness down) */ - KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */ - KEY_UNKNOWN, /* 0x12: FN+PGDOWN */ KEY_ZOOM, /* 0x13: FN+SPACE (zoom) */ - - /* Volume: z60/z61, T60 (BIOS version?): firmware always - * react to it and reprograms the built-in *extra* mixer. - * Never map it to control another mixer by default. - * - * T60?, T61, R60?, R61: firmware and EC tries to send - * these over the regular keyboard, so these are no-ops, - * but there are still weird bugs re. MUTE, so do not - * change unless you get test reports from all Lenovo - * models. May cause the BIOS to interfere with the - * HDA mixer. - */ KEY_RESERVED, /* 0x14: VOLUME UP */ KEY_RESERVED, /* 0x15: VOLUME DOWN */ KEY_RESERVED, /* 0x16: MUTE */ - KEY_VENDOR, /* 0x17: Thinkpad/AccessIBM/Lenovo */ - /* (assignments unknown, please report if found) */ KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, @@ -1860,17 +1013,10 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) vdbg_printk(TPACPI_DBG_INIT, "initializing hotkey subdriver\n"); BUG_ON(!tpacpi_inputdev); - BUG_ON(tpacpi_inputdev->open != NULL || - tpacpi_inputdev->close != NULL); - TPACPI_ACPIHANDLE_INIT(hkey); + IBM_ACPIHANDLE_INIT(hkey); mutex_init(&hotkey_mutex); -#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL - mutex_init(&hotkey_thread_mutex); - mutex_init(&hotkey_thread_data_mutex); -#endif - /* hotkey not supported on 570 */ tp_features.hotkey = hkey_handle != NULL; @@ -1878,7 +1024,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) str_supported(tp_features.hotkey)); if (tp_features.hotkey) { - hotkey_dev_attributes = create_attr_set(12, NULL); + hotkey_dev_attributes = create_attr_set(8, NULL); if (!hotkey_dev_attributes) return -ENOMEM; res = add_many_to_attr_set(hotkey_dev_attributes, @@ -1892,15 +1038,15 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) for HKEY interface version 0x100 */ if (acpi_evalf(hkey_handle, &hkeyv, "MHKV", "qd")) { if ((hkeyv >> 8) != 1) { - printk(TPACPI_ERR "unknown version of the " + printk(IBM_ERR "unknown version of the " "HKEY interface: 0x%x\n", hkeyv); - printk(TPACPI_ERR "please report this to %s\n", - TPACPI_MAIL); + printk(IBM_ERR "please report this to %s\n", + IBM_MAIL); } else { /* * MHKV 0x100 in A31, R40, R40e, * T4x, X31, and later - */ + * */ tp_features.hotkey_mask = 1; } } @@ -1911,46 +1057,25 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) if (tp_features.hotkey_mask) { if (!acpi_evalf(hkey_handle, &hotkey_all_mask, "MHKA", "qd")) { - printk(TPACPI_ERR + printk(IBM_ERR "missing MHKA handler, " "please report this to %s\n", - TPACPI_MAIL); - /* FN+F12, FN+F4, FN+F3 */ - hotkey_all_mask = 0x080cU; + IBM_MAIL); + hotkey_all_mask = 0x080cU; /* FN+F12, FN+F4, FN+F3 */ } } - /* hotkey_source_mask *must* be zero for - * the first hotkey_mask_get */ - res = hotkey_status_get(&hotkey_orig_status); + res = hotkey_get(&hotkey_orig_status, &hotkey_orig_mask); if (!res && tp_features.hotkey_mask) { - res = hotkey_mask_get(); - hotkey_orig_mask = hotkey_mask; - if (!res) { - res = add_many_to_attr_set( - hotkey_dev_attributes, - hotkey_mask_attributes, - ARRAY_SIZE(hotkey_mask_attributes)); - } - } - -#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL - if (tp_features.hotkey_mask) { - hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK - & ~hotkey_all_mask; - } else { - hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK; + res = add_many_to_attr_set(hotkey_dev_attributes, + hotkey_mask_attributes, + ARRAY_SIZE(hotkey_mask_attributes)); } - vdbg_printk(TPACPI_DBG_INIT, - "hotkey source mask 0x%08x, polling freq %d\n", - hotkey_source_mask, hotkey_poll_freq); -#endif - /* Not all thinkpads have a hardware radio switch */ if (!res && acpi_evalf(hkey_handle, &status, "WLSW", "qd")) { tp_features.hotkey_wlsw = 1; - printk(TPACPI_INFO + printk(IBM_INFO "radio switch found; radios are %s\n", enabled(status, 0)); res = add_to_attr_set(hotkey_dev_attributes, @@ -1969,8 +1094,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) hotkey_keycode_map = kmalloc(TPACPI_HOTKEY_MAP_SIZE, GFP_KERNEL); if (!hotkey_keycode_map) { - printk(TPACPI_ERR - "failed to allocate memory for key map\n"); + printk(IBM_ERR "failed to allocate memory for key map\n"); return -ENOMEM; } @@ -2009,26 +1133,15 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) dbg_printk(TPACPI_DBG_INIT, "enabling hot key handling\n"); - res = hotkey_status_set(1); - if (res) - return res; - res = hotkey_mask_set(((hotkey_all_mask | hotkey_source_mask) - & ~hotkey_reserved_mask) + res = hotkey_set(1, (hotkey_all_mask & ~hotkey_reserved_mask) | hotkey_orig_mask); - if (res < 0 && res != -ENXIO) + if (res) return res; dbg_printk(TPACPI_DBG_INIT, "legacy hot key reporting over procfs %s\n", (hotkey_report_mode < 2) ? "enabled" : "disabled"); - -#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL - tpacpi_inputdev->open = &hotkey_inputdev_open; - tpacpi_inputdev->close = &hotkey_inputdev_close; - - hotkey_poll_setup_safe(1); -#endif } return (tp_features.hotkey)? 0 : 1; @@ -2036,19 +1149,13 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) static void hotkey_exit(void) { -#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL - hotkey_poll_stop_sync(); -#endif + int res; if (tp_features.hotkey) { - dbg_printk(TPACPI_DBG_EXIT, - "restoring original hot key mask\n"); - /* no short-circuit boolean operator below! */ - if ((hotkey_mask_set(hotkey_orig_mask) | - hotkey_status_set(hotkey_orig_status)) != 0) - printk(TPACPI_ERR - "failed to restore hot key mask " - "to BIOS defaults\n"); + dbg_printk(TPACPI_DBG_EXIT, "restoring original hotkey mask\n"); + res = hotkey_set(hotkey_orig_status, hotkey_orig_mask); + if (res) + printk(IBM_ERR "failed to restore hotkey to BIOS defaults\n"); } if (hotkey_dev_attributes) { @@ -2057,28 +1164,62 @@ static void hotkey_exit(void) } } +static void tpacpi_input_send_key(unsigned int scancode, + unsigned int keycode) +{ + if (keycode != KEY_RESERVED) { + mutex_lock(&tpacpi_inputdev_send_mutex); + + input_report_key(tpacpi_inputdev, keycode, 1); + if (keycode == KEY_UNKNOWN) + input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN, + scancode); + input_sync(tpacpi_inputdev); + + input_report_key(tpacpi_inputdev, keycode, 0); + if (keycode == KEY_UNKNOWN) + input_event(tpacpi_inputdev, EV_MSC, MSC_SCAN, + scancode); + input_sync(tpacpi_inputdev); + + mutex_unlock(&tpacpi_inputdev_send_mutex); + } +} + +static void tpacpi_input_send_radiosw(void) +{ + int wlsw; + + mutex_lock(&tpacpi_inputdev_send_mutex); + + if (tp_features.hotkey_wlsw && !hotkey_get_wlsw(&wlsw)) { + input_report_switch(tpacpi_inputdev, + SW_RADIO, !!wlsw); + input_sync(tpacpi_inputdev); + } + + mutex_unlock(&tpacpi_inputdev_send_mutex); +} + static void hotkey_notify(struct ibm_struct *ibm, u32 event) { u32 hkey; - unsigned int scancode; + unsigned int keycode, scancode; int send_acpi_ev; int ignore_acpi_ev; - int unk_ev; if (event != 0x80) { - printk(TPACPI_ERR - "unknown HKEY notification event %d\n", event); + printk(IBM_ERR "unknown HKEY notification event %d\n", event); /* forward it to userspace, maybe it knows how to handle it */ - acpi_bus_generate_netlink_event( - ibm->acpi->device->pnp.device_class, - ibm->acpi->device->dev.bus_id, - event, 0); + acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class, + ibm->acpi->device->dev.bus_id, + event, 0); return; } while (1) { if (!acpi_evalf(hkey_handle, &hkey, "MHKP", "d")) { - printk(TPACPI_ERR "failed to retrieve HKEY event\n"); + printk(IBM_ERR "failed to retrieve HKEY event\n"); return; } @@ -2087,9 +1228,8 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event) return; } - send_acpi_ev = 1; + send_acpi_ev = 0; ignore_acpi_ev = 0; - unk_ev = 0; switch (hkey >> 12) { case 1: @@ -2097,139 +1237,104 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event) scancode = hkey & 0xfff; if (scancode > 0 && scancode < 0x21) { scancode--; - if (!(hotkey_source_mask & (1 << scancode))) { - tpacpi_input_send_key(scancode); - send_acpi_ev = 0; - } else { - ignore_acpi_ev = 1; - } - } else { - unk_ev = 1; - } - break; - case 2: - /* Wakeup reason */ - switch (hkey) { - case 0x2304: /* suspend, undock */ - case 0x2404: /* hibernation, undock */ - hotkey_wakeup_reason = TP_ACPI_WAKEUP_UNDOCK; - ignore_acpi_ev = 1; - break; - case 0x2305: /* suspend, bay eject */ - case 0x2405: /* hibernation, bay eject */ - hotkey_wakeup_reason = TP_ACPI_WAKEUP_BAYEJ; - ignore_acpi_ev = 1; - break; - default: - unk_ev = 1; - } - if (hotkey_wakeup_reason != TP_ACPI_WAKEUP_NONE) { - printk(TPACPI_INFO - "woke up due to a hot-unplug " - "request...\n"); - hotkey_wakeup_reason_notify_change(); - } - break; - case 3: - /* bay-related wakeups */ - if (hkey == 0x3003) { - hotkey_autosleep_ack = 1; - printk(TPACPI_INFO - "bay ejected\n"); - hotkey_wakeup_hotunplug_complete_notify_change(); + keycode = hotkey_keycode_map[scancode]; + tpacpi_input_send_key(scancode, keycode); } else { - unk_ev = 1; - } - break; - case 4: - /* dock-related wakeups */ - if (hkey == 0x4003) { - hotkey_autosleep_ack = 1; - printk(TPACPI_INFO - "undocked\n"); - hotkey_wakeup_hotunplug_complete_notify_change(); - } else { - unk_ev = 1; + printk(IBM_ERR + "hotkey 0x%04x out of range for keyboard map\n", + hkey); + send_acpi_ev = 1; } break; case 5: - /* 0x5000-0x5FFF: human interface helpers */ - switch (hkey) { - case 0x5010: /* Lenovo new BIOS: brightness changed */ - case 0x5009: /* X61t: swivel up (tablet mode) */ - case 0x500a: /* X61t: swivel down (normal mode) */ - case 0x500b: /* X61t: tablet pen inserted into bay */ - case 0x500c: /* X61t: tablet pen removed from bay */ - break; - case 0x5001: - case 0x5002: - /* LID switch events. Do not propagate */ + /* 0x5000-0x5FFF: LID */ + /* we don't handle it through this path, just + * eat up known LID events */ + if (hkey != 0x5001 && hkey != 0x5002) { + printk(IBM_ERR + "unknown LID-related HKEY event: 0x%04x\n", + hkey); + send_acpi_ev = 1; + } else { ignore_acpi_ev = 1; - break; - default: - unk_ev = 1; } break; case 7: /* 0x7000-0x7FFF: misc */ if (tp_features.hotkey_wlsw && hkey == 0x7000) { tpacpi_input_send_radiosw(); - hotkey_radio_sw_notify_change(); - send_acpi_ev = 0; break; } /* fallthrough to default */ default: - unk_ev = 1; - } - if (unk_ev) { - printk(TPACPI_NOTICE - "unhandled HKEY event 0x%04x\n", hkey); + /* case 2: dock-related */ + /* 0x2305 - T43 waking up due to bay lever eject while aslept */ + /* case 3: ultra-bay related. maybe bay in dock? */ + /* 0x3003 - T43 after wake up by bay lever eject (0x2305) */ + printk(IBM_NOTICE "unhandled HKEY event 0x%04x\n", hkey); + send_acpi_ev = 1; } /* Legacy events */ - if (!ignore_acpi_ev && - (send_acpi_ev || hotkey_report_mode < 2)) { - acpi_bus_generate_proc_event(ibm->acpi->device, - event, hkey); + if (!ignore_acpi_ev && (send_acpi_ev || hotkey_report_mode < 2)) { + acpi_bus_generate_proc_event(ibm->acpi->device, event, hkey); } /* netlink events */ if (!ignore_acpi_ev && send_acpi_ev) { - acpi_bus_generate_netlink_event( - ibm->acpi->device->pnp.device_class, - ibm->acpi->device->dev.bus_id, - event, hkey); + acpi_bus_generate_netlink_event(ibm->acpi->device->pnp.device_class, + ibm->acpi->device->dev.bus_id, + event, hkey); } } } -static void hotkey_suspend(pm_message_t state) +static void hotkey_resume(void) { - /* Do these on suspend, we get the events on early resume! */ - hotkey_wakeup_reason = TP_ACPI_WAKEUP_NONE; - hotkey_autosleep_ack = 0; + tpacpi_input_send_radiosw(); } -static void hotkey_resume(void) +/* + * Call with hotkey_mutex held + */ +static int hotkey_get(int *status, u32 *mask) { - if (hotkey_mask_get()) - printk(TPACPI_ERR - "error while trying to read hot key mask " - "from firmware\n"); - tpacpi_input_send_radiosw(); - hotkey_radio_sw_notify_change(); - hotkey_wakeup_reason_notify_change(); - hotkey_wakeup_hotunplug_complete_notify_change(); -#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL - hotkey_poll_setup_safe(0); -#endif + if (!acpi_evalf(hkey_handle, status, "DHKC", "d")) + return -EIO; + + if (tp_features.hotkey_mask) + if (!acpi_evalf(hkey_handle, mask, "DHKN", "d")) + return -EIO; + + return 0; +} + +/* + * Call with hotkey_mutex held + */ +static int hotkey_set(int status, u32 mask) +{ + int i; + + if (!acpi_evalf(hkey_handle, NULL, "MHKC", "vd", status)) + return -EIO; + + if (tp_features.hotkey_mask) + for (i = 0; i < 32; i++) { + int bit = ((1 << i) & mask) != 0; + if (!acpi_evalf(hkey_handle, + NULL, "MHKM", "vdd", i + 1, bit)) + return -EIO; + } + + return 0; } /* procfs -------------------------------------------------------------- */ static int hotkey_read(char *p) { int res, status; + u32 mask; int len = 0; if (!tp_features.hotkey) { @@ -2239,16 +1344,14 @@ static int hotkey_read(char *p) if (mutex_lock_interruptible(&hotkey_mutex)) return -ERESTARTSYS; - res = hotkey_status_get(&status); - if (!res) - res = hotkey_mask_get(); + res = hotkey_get(&status, &mask); mutex_unlock(&hotkey_mutex); if (res) return res; len += sprintf(p + len, "status:\t\t%s\n", enabled(status, 0)); if (tp_features.hotkey_mask) { - len += sprintf(p + len, "mask:\t\t0x%08x\n", hotkey_mask); + len += sprintf(p + len, "mask:\t\t0x%08x\n", mask); len += sprintf(p + len, "commands:\tenable, disable, reset, \n"); } else { @@ -2264,6 +1367,7 @@ static int hotkey_write(char *buf) int res, status; u32 mask; char *cmd; + int do_cmd = 0; if (!tp_features.hotkey) return -ENODEV; @@ -2271,8 +1375,9 @@ static int hotkey_write(char *buf) if (mutex_lock_interruptible(&hotkey_mutex)) return -ERESTARTSYS; - status = -1; - mask = hotkey_mask; + res = hotkey_get(&status, &mask); + if (res) + goto errexit; res = 0; while ((cmd = next_cmd(&buf))) { @@ -2291,12 +1396,11 @@ static int hotkey_write(char *buf) res = -EINVAL; goto errexit; } + do_cmd = 1; } - if (status != -1) - res = hotkey_status_set(status); - if (!res && mask != hotkey_mask) - res = hotkey_mask_set(mask); + if (do_cmd) + res = hotkey_set(status, mask); errexit: mutex_unlock(&hotkey_mutex); @@ -2304,7 +1408,7 @@ static int hotkey_write(char *buf) } static const struct acpi_device_id ibm_htk_device_ids[] = { - {TPACPI_ACPI_HKEY_HID, 0}, + {IBM_HKEY_HID, 0}, {"", 0}, }; @@ -2321,7 +1425,6 @@ static struct ibm_struct hotkey_driver_data = { .write = hotkey_write, .exit = hotkey_exit, .resume = hotkey_resume, - .suspend = hotkey_suspend, .acpi = &ibm_hotkey_acpidriver, }; @@ -2329,16 +1432,6 @@ static struct ibm_struct hotkey_driver_data = { * Bluetooth subdriver */ -enum { - /* ACPI GBDC/SBDC bits */ - TP_ACPI_BLUETOOTH_HWPRESENT = 0x01, /* Bluetooth hw available */ - TP_ACPI_BLUETOOTH_RADIOSSW = 0x02, /* Bluetooth radio enabled */ - TP_ACPI_BLUETOOTH_UNK = 0x04, /* unknown function */ -}; - -static int bluetooth_get_radiosw(void); -static int bluetooth_set_radiosw(int radio_on); - /* sysfs bluetooth enable ---------------------------------------------- */ static ssize_t bluetooth_enable_show(struct device *dev, struct device_attribute *attr, @@ -2390,7 +1483,7 @@ static int __init bluetooth_init(struct ibm_init_struct *iibm) vdbg_printk(TPACPI_DBG_INIT, "initializing bluetooth subdriver\n"); - TPACPI_ACPIHANDLE_INIT(hkey); + IBM_ACPIHANDLE_INIT(hkey); /* bluetooth not supported on 570, 600e/x, 770e, 770x, A21e, A2xm/p, G4x, R30, R31, R40e, R50e, T20-22, X20-21 */ @@ -2503,16 +1596,6 @@ static struct ibm_struct bluetooth_driver_data = { * Wan subdriver */ -enum { - /* ACPI GWAN/SWAN bits */ - TP_ACPI_WANCARD_HWPRESENT = 0x01, /* Wan hw available */ - TP_ACPI_WANCARD_RADIOSSW = 0x02, /* Wan radio enabled */ - TP_ACPI_WANCARD_UNK = 0x04, /* unknown function */ -}; - -static int wan_get_radiosw(void); -static int wan_set_radiosw(int radio_on); - /* sysfs wan enable ---------------------------------------------------- */ static ssize_t wan_enable_show(struct device *dev, struct device_attribute *attr, @@ -2564,7 +1647,7 @@ static int __init wan_init(struct ibm_init_struct *iibm) vdbg_printk(TPACPI_DBG_INIT, "initializing wan subdriver\n"); - TPACPI_ACPIHANDLE_INIT(hkey); + IBM_ACPIHANDLE_INIT(hkey); tp_features.wan = hkey_handle && acpi_evalf(hkey_handle, &status, "GWAN", "qd"); @@ -2676,41 +1759,17 @@ static struct ibm_struct wan_driver_data = { * Video subdriver */ -enum video_access_mode { - TPACPI_VIDEO_NONE = 0, - TPACPI_VIDEO_570, /* 570 */ - TPACPI_VIDEO_770, /* 600e/x, 770e, 770x */ - TPACPI_VIDEO_NEW, /* all others */ -}; - -enum { /* video status flags, based on VIDEO_570 */ - TP_ACPI_VIDEO_S_LCD = 0x01, /* LCD output enabled */ - TP_ACPI_VIDEO_S_CRT = 0x02, /* CRT output enabled */ - TP_ACPI_VIDEO_S_DVI = 0x08, /* DVI output enabled */ -}; - -enum { /* TPACPI_VIDEO_570 constants */ - TP_ACPI_VIDEO_570_PHSCMD = 0x87, /* unknown magic constant :( */ - TP_ACPI_VIDEO_570_PHSMASK = 0x03, /* PHS bits that map to - * video_status_flags */ - TP_ACPI_VIDEO_570_PHS2CMD = 0x8b, /* unknown magic constant :( */ - TP_ACPI_VIDEO_570_PHS2SET = 0x80, /* unknown magic constant :( */ -}; - static enum video_access_mode video_supported; static int video_orig_autosw; -static int video_autosw_get(void); -static int video_autosw_set(int enable); - -TPACPI_HANDLE(vid, root, "\\_SB.PCI.AGP.VGA", /* 570 */ +IBM_HANDLE(vid, root, "\\_SB.PCI.AGP.VGA", /* 570 */ "\\_SB.PCI0.AGP0.VID0", /* 600e/x, 770x */ "\\_SB.PCI0.VID0", /* 770e */ "\\_SB.PCI0.VID", /* A21e, G4x, R50e, X30, X40 */ "\\_SB.PCI0.AGP.VID", /* all others */ ); /* R30, R31 */ -TPACPI_HANDLE(vid2, root, "\\_SB.PCI0.AGPB.VID"); /* G41 */ +IBM_HANDLE(vid2, root, "\\_SB.PCI0.AGPB.VID"); /* G41 */ static int __init video_init(struct ibm_init_struct *iibm) { @@ -2718,8 +1777,8 @@ static int __init video_init(struct ibm_init_struct *iibm) vdbg_printk(TPACPI_DBG_INIT, "initializing video subdriver\n"); - TPACPI_ACPIHANDLE_INIT(vid); - TPACPI_ACPIHANDLE_INIT(vid2); + IBM_ACPIHANDLE_INIT(vid); + IBM_ACPIHANDLE_INIT(vid2); if (vid2_handle && acpi_evalf(NULL, &ivga, "\\IVGA", "d") && ivga) /* G41, assume IVGA doesn't change */ @@ -2750,7 +1809,7 @@ static void video_exit(void) dbg_printk(TPACPI_DBG_EXIT, "restoring original video autoswitch mode\n"); if (video_autosw_set(video_orig_autosw)) - printk(TPACPI_ERR "error while trying to restore original " + printk(IBM_ERR "error while trying to restore original " "video autoswitch mode\n"); } @@ -2823,14 +1882,13 @@ static int video_outputsw_set(int status) res = acpi_evalf(vid_handle, NULL, "ASWT", "vdd", status * 0x100, 0); if (!autosw && video_autosw_set(autosw)) { - printk(TPACPI_ERR - "video auto-switch left enabled due to error\n"); + printk(IBM_ERR "video auto-switch left enabled due to error\n"); return -EIO; } break; case TPACPI_VIDEO_NEW: res = acpi_evalf(NULL, NULL, "\\VUPS", "vd", 0x80) && - acpi_evalf(NULL, NULL, "\\VSDS", "vdd", status, 1); + acpi_evalf(NULL, NULL, "\\VSDS", "vdd", status, 1); break; default: return -ENOSYS; @@ -2893,8 +1951,7 @@ static int video_outputsw_cycle(void) return -ENOSYS; } if (!autosw && video_autosw_set(autosw)) { - printk(TPACPI_ERR - "video auto-switch left enabled due to error\n"); + printk(IBM_ERR "video auto-switch left enabled due to error\n"); return -EIO; } @@ -3023,16 +2080,16 @@ static struct ibm_struct video_driver_data = { * Light (thinklight) subdriver */ -TPACPI_HANDLE(lght, root, "\\LGHT"); /* A21e, A2xm/p, T20-22, X20-21 */ -TPACPI_HANDLE(ledb, ec, "LEDB"); /* G4x */ +IBM_HANDLE(lght, root, "\\LGHT"); /* A21e, A2xm/p, T20-22, X20-21 */ +IBM_HANDLE(ledb, ec, "LEDB"); /* G4x */ static int __init light_init(struct ibm_init_struct *iibm) { vdbg_printk(TPACPI_DBG_INIT, "initializing light subdriver\n"); - TPACPI_ACPIHANDLE_INIT(ledb); - TPACPI_ACPIHANDLE_INIT(lght); - TPACPI_ACPIHANDLE_INIT(cmos); + IBM_ACPIHANDLE_INIT(ledb); + IBM_ACPIHANDLE_INIT(lght); + IBM_ACPIHANDLE_INIT(cmos); /* light not supported on 570, 600e/x, 770e, 770x, G4x, R30, R31 */ tp_features.light = (cmos_handle || lght_handle) && !ledb_handle; @@ -3110,18 +2167,14 @@ static struct ibm_struct light_driver_data = { #ifdef CONFIG_THINKPAD_ACPI_DOCK -static void dock_notify(struct ibm_struct *ibm, u32 event); -static int dock_read(char *p); -static int dock_write(char *buf); - -TPACPI_HANDLE(dock, root, "\\_SB.GDCK", /* X30, X31, X40 */ +IBM_HANDLE(dock, root, "\\_SB.GDCK", /* X30, X31, X40 */ "\\_SB.PCI0.DOCK", /* 600e/x,770e,770x,A2xm/p,T20-22,X20-21 */ "\\_SB.PCI0.PCI1.DOCK", /* all others */ "\\_SB.PCI.ISA.SLCE", /* 570 */ ); /* A21e,G4x,R30,R31,R32,R40,R40e,R50e */ /* don't list other alternatives as we install a notify handler on the 570 */ -TPACPI_HANDLE(pci, root, "\\_SB.PCI"); /* 570 */ +IBM_HANDLE(pci, root, "\\_SB.PCI"); /* 570 */ static const struct acpi_device_id ibm_pci_device_ids[] = { {PCI_ROOT_HID_STRING, 0}, @@ -3164,7 +2217,7 @@ static int __init dock_init(struct ibm_init_struct *iibm) { vdbg_printk(TPACPI_DBG_INIT, "initializing dock subdriver\n"); - TPACPI_ACPIHANDLE_INIT(dock); + IBM_ACPIHANDLE_INIT(dock); vdbg_printk(TPACPI_DBG_INIT, "dock is %s\n", str_supported(dock_handle != NULL)); @@ -3180,7 +2233,7 @@ static int __init dock_init2(struct ibm_init_struct *iibm) if (dock_driver_data[0].flags.acpi_driver_registered && dock_driver_data[0].flags.acpi_notify_installed) { - TPACPI_ACPIHANDLE_INIT(pci); + IBM_ACPIHANDLE_INIT(pci); dock2_needed = (pci_handle != NULL); vdbg_printk(TPACPI_DBG_INIT, "dock PCI handler for the TP 570 is %s\n", @@ -3212,7 +2265,7 @@ static void dock_notify(struct ibm_struct *ibm, u32 event) else if (event == 0 && docked) data = 3; /* dock */ else { - printk(TPACPI_ERR "unknown dock event %d, status %d\n", + printk(IBM_ERR "unknown dock event %d, status %d\n", event, _sta(dock_handle)); data = 0; /* unknown */ } @@ -3268,19 +2321,18 @@ static int dock_write(char *buf) */ #ifdef CONFIG_THINKPAD_ACPI_BAY - -TPACPI_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST", /* 570 */ +IBM_HANDLE(bay, root, "\\_SB.PCI.IDE.SECN.MAST", /* 570 */ "\\_SB.PCI0.IDE0.IDES.IDSM", /* 600e/x, 770e, 770x */ "\\_SB.PCI0.SATA.SCND.MSTR", /* T60, X60, Z60 */ "\\_SB.PCI0.IDE0.SCND.MSTR", /* all others */ ); /* A21e, R30, R31 */ -TPACPI_HANDLE(bay_ej, bay, "_EJ3", /* 600e/x, A2xm/p, A3x */ +IBM_HANDLE(bay_ej, bay, "_EJ3", /* 600e/x, A2xm/p, A3x */ "_EJ0", /* all others */ ); /* 570,A21e,G4x,R30,R31,R32,R40e,R50e */ -TPACPI_HANDLE(bay2, root, "\\_SB.PCI0.IDE0.PRIM.SLAV", /* A3x, R32 */ +IBM_HANDLE(bay2, root, "\\_SB.PCI0.IDE0.PRIM.SLAV", /* A3x, R32 */ "\\_SB.PCI0.IDE0.IDEP.IDPS", /* 600e/x, 770e, 770x */ ); /* all others */ -TPACPI_HANDLE(bay2_ej, bay2, "_EJ3", /* 600e/x, 770e, A3x */ +IBM_HANDLE(bay2_ej, bay2, "_EJ3", /* 600e/x, 770e, A3x */ "_EJ0", /* 770x */ ); /* all others */ @@ -3288,12 +2340,12 @@ static int __init bay_init(struct ibm_init_struct *iibm) { vdbg_printk(TPACPI_DBG_INIT, "initializing bay subdriver\n"); - TPACPI_ACPIHANDLE_INIT(bay); + IBM_ACPIHANDLE_INIT(bay); if (bay_handle) - TPACPI_ACPIHANDLE_INIT(bay_ej); - TPACPI_ACPIHANDLE_INIT(bay2); + IBM_ACPIHANDLE_INIT(bay_ej); + IBM_ACPIHANDLE_INIT(bay2); if (bay2_handle) - TPACPI_ACPIHANDLE_INIT(bay2_ej); + IBM_ACPIHANDLE_INIT(bay2_ej); tp_features.bay_status = bay_handle && acpi_evalf(bay_handle, NULL, "_STA", "qv"); @@ -3422,7 +2474,7 @@ static int __init cmos_init(struct ibm_init_struct *iibm) vdbg_printk(TPACPI_DBG_INIT, "initializing cmos commands subdriver\n"); - TPACPI_ACPIHANDLE_INIT(cmos); + IBM_ACPIHANDLE_INIT(cmos); vdbg_printk(TPACPI_DBG_INIT, "cmos commands are %s\n", str_supported(cmos_handle != NULL)); @@ -3486,24 +2538,10 @@ static struct ibm_struct cmos_driver_data = { * LED subdriver */ -enum led_access_mode { - TPACPI_LED_NONE = 0, - TPACPI_LED_570, /* 570 */ - TPACPI_LED_OLD, /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */ - TPACPI_LED_NEW, /* all others */ -}; - -enum { /* For TPACPI_LED_OLD */ - TPACPI_LED_EC_HLCL = 0x0c, /* EC reg to get led to power on */ - TPACPI_LED_EC_HLBL = 0x0d, /* EC reg to blink a lit led */ - TPACPI_LED_EC_HLMS = 0x0e, /* EC reg to select led to command */ -}; - static enum led_access_mode led_supported; -TPACPI_HANDLE(led, ec, "SLED", /* 570 */ - "SYSL", /* 600e/x, 770e, 770x, A21e, A2xm/p, */ - /* T20-22, X20-21 */ +IBM_HANDLE(led, ec, "SLED", /* 570 */ + "SYSL", /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */ "LED", /* all others */ ); /* R30, R31 */ @@ -3511,7 +2549,7 @@ static int __init led_init(struct ibm_init_struct *iibm) { vdbg_printk(TPACPI_DBG_INIT, "initializing LED subdriver\n"); - TPACPI_ACPIHANDLE_INIT(led); + IBM_ACPIHANDLE_INIT(led); if (!led_handle) /* led not supported on R30, R31 */ @@ -3600,11 +2638,13 @@ static int led_write(char *buf) led = 1 << led; ret = ec_write(TPACPI_LED_EC_HLMS, led); if (ret >= 0) - ret = ec_write(TPACPI_LED_EC_HLBL, - led * led_exp_hlbl[ind]); + ret = + ec_write(TPACPI_LED_EC_HLBL, + led * led_exp_hlbl[ind]); if (ret >= 0) - ret = ec_write(TPACPI_LED_EC_HLCL, - led * led_exp_hlcl[ind]); + ret = + ec_write(TPACPI_LED_EC_HLCL, + led * led_exp_hlcl[ind]); if (ret < 0) return ret; } else { @@ -3628,13 +2668,13 @@ static struct ibm_struct led_driver_data = { * Beep subdriver */ -TPACPI_HANDLE(beep, ec, "BEEP"); /* all except R30, R31 */ +IBM_HANDLE(beep, ec, "BEEP"); /* all except R30, R31 */ static int __init beep_init(struct ibm_init_struct *iibm) { vdbg_printk(TPACPI_DBG_INIT, "initializing beep subdriver\n"); - TPACPI_ACPIHANDLE_INIT(beep); + IBM_ACPIHANDLE_INIT(beep); vdbg_printk(TPACPI_DBG_INIT, "beep is %s\n", str_supported(beep_handle != NULL)); @@ -3687,155 +2727,53 @@ static struct ibm_struct beep_driver_data = { * Thermal subdriver */ -enum thermal_access_mode { - TPACPI_THERMAL_NONE = 0, /* No thermal support */ - TPACPI_THERMAL_ACPI_TMP07, /* Use ACPI TMP0-7 */ - TPACPI_THERMAL_ACPI_UPDT, /* Use ACPI TMP0-7 with UPDT */ - TPACPI_THERMAL_TPEC_8, /* Use ACPI EC regs, 8 sensors */ - TPACPI_THERMAL_TPEC_16, /* Use ACPI EC regs, 16 sensors */ -}; +static enum thermal_access_mode thermal_read_mode; -enum { /* TPACPI_THERMAL_TPEC_* */ - TP_EC_THERMAL_TMP0 = 0x78, /* ACPI EC regs TMP 0..7 */ - TP_EC_THERMAL_TMP8 = 0xC0, /* ACPI EC regs TMP 8..15 */ - TP_EC_THERMAL_TMP_NA = -128, /* ACPI EC sensor not available */ -}; +/* sysfs temp##_input -------------------------------------------------- */ -#define TPACPI_MAX_THERMAL_SENSORS 16 /* Max thermal sensors supported */ -struct ibm_thermal_sensors_struct { - s32 temp[TPACPI_MAX_THERMAL_SENSORS]; -}; +static ssize_t thermal_temp_input_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sensor_attr = + to_sensor_dev_attr(attr); + int idx = sensor_attr->index; + s32 value; + int res; -static enum thermal_access_mode thermal_read_mode; + res = thermal_get_sensor(idx, &value); + if (res) + return res; + if (value == TP_EC_THERMAL_TMP_NA * 1000) + return -ENXIO; -/* idx is zero-based */ -static int thermal_get_sensor(int idx, s32 *value) -{ - int t; - s8 tmp; - char tmpi[5]; + return snprintf(buf, PAGE_SIZE, "%d\n", value); +} - t = TP_EC_THERMAL_TMP0; +#define THERMAL_SENSOR_ATTR_TEMP(_idxA, _idxB) \ + SENSOR_ATTR(temp##_idxA##_input, S_IRUGO, thermal_temp_input_show, NULL, _idxB) - switch (thermal_read_mode) { -#if TPACPI_MAX_THERMAL_SENSORS >= 16 - case TPACPI_THERMAL_TPEC_16: - if (idx >= 8 && idx <= 15) { - t = TP_EC_THERMAL_TMP8; - idx -= 8; - } - /* fallthrough */ -#endif - case TPACPI_THERMAL_TPEC_8: - if (idx <= 7) { - if (!acpi_ec_read(t + idx, &tmp)) - return -EIO; - *value = tmp * 1000; - return 0; - } - break; +static struct sensor_device_attribute sensor_dev_attr_thermal_temp_input[] = { + THERMAL_SENSOR_ATTR_TEMP(1, 0), + THERMAL_SENSOR_ATTR_TEMP(2, 1), + THERMAL_SENSOR_ATTR_TEMP(3, 2), + THERMAL_SENSOR_ATTR_TEMP(4, 3), + THERMAL_SENSOR_ATTR_TEMP(5, 4), + THERMAL_SENSOR_ATTR_TEMP(6, 5), + THERMAL_SENSOR_ATTR_TEMP(7, 6), + THERMAL_SENSOR_ATTR_TEMP(8, 7), + THERMAL_SENSOR_ATTR_TEMP(9, 8), + THERMAL_SENSOR_ATTR_TEMP(10, 9), + THERMAL_SENSOR_ATTR_TEMP(11, 10), + THERMAL_SENSOR_ATTR_TEMP(12, 11), + THERMAL_SENSOR_ATTR_TEMP(13, 12), + THERMAL_SENSOR_ATTR_TEMP(14, 13), + THERMAL_SENSOR_ATTR_TEMP(15, 14), + THERMAL_SENSOR_ATTR_TEMP(16, 15), +}; - case TPACPI_THERMAL_ACPI_UPDT: - if (idx <= 7) { - snprintf(tmpi, sizeof(tmpi), "TMP%c", '0' + idx); - if (!acpi_evalf(ec_handle, NULL, "UPDT", "v")) - return -EIO; - if (!acpi_evalf(ec_handle, &t, tmpi, "d")) - return -EIO; - *value = (t - 2732) * 100; - return 0; - } - break; - - case TPACPI_THERMAL_ACPI_TMP07: - if (idx <= 7) { - snprintf(tmpi, sizeof(tmpi), "TMP%c", '0' + idx); - if (!acpi_evalf(ec_handle, &t, tmpi, "d")) - return -EIO; - if (t > 127 || t < -127) - t = TP_EC_THERMAL_TMP_NA; - *value = t * 1000; - return 0; - } - break; - - case TPACPI_THERMAL_NONE: - default: - return -ENOSYS; - } - - return -EINVAL; -} - -static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s) -{ - int res, i; - int n; - - n = 8; - i = 0; - - if (!s) - return -EINVAL; - - if (thermal_read_mode == TPACPI_THERMAL_TPEC_16) - n = 16; - - for (i = 0 ; i < n; i++) { - res = thermal_get_sensor(i, &s->temp[i]); - if (res) - return res; - } - - return n; -} - -/* sysfs temp##_input -------------------------------------------------- */ - -static ssize_t thermal_temp_input_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = - to_sensor_dev_attr(attr); - int idx = sensor_attr->index; - s32 value; - int res; - - res = thermal_get_sensor(idx, &value); - if (res) - return res; - if (value == TP_EC_THERMAL_TMP_NA * 1000) - return -ENXIO; - - return snprintf(buf, PAGE_SIZE, "%d\n", value); -} - -#define THERMAL_SENSOR_ATTR_TEMP(_idxA, _idxB) \ - SENSOR_ATTR(temp##_idxA##_input, S_IRUGO, \ - thermal_temp_input_show, NULL, _idxB) - -static struct sensor_device_attribute sensor_dev_attr_thermal_temp_input[] = { - THERMAL_SENSOR_ATTR_TEMP(1, 0), - THERMAL_SENSOR_ATTR_TEMP(2, 1), - THERMAL_SENSOR_ATTR_TEMP(3, 2), - THERMAL_SENSOR_ATTR_TEMP(4, 3), - THERMAL_SENSOR_ATTR_TEMP(5, 4), - THERMAL_SENSOR_ATTR_TEMP(6, 5), - THERMAL_SENSOR_ATTR_TEMP(7, 6), - THERMAL_SENSOR_ATTR_TEMP(8, 7), - THERMAL_SENSOR_ATTR_TEMP(9, 8), - THERMAL_SENSOR_ATTR_TEMP(10, 9), - THERMAL_SENSOR_ATTR_TEMP(11, 10), - THERMAL_SENSOR_ATTR_TEMP(12, 11), - THERMAL_SENSOR_ATTR_TEMP(13, 12), - THERMAL_SENSOR_ATTR_TEMP(14, 13), - THERMAL_SENSOR_ATTR_TEMP(15, 14), - THERMAL_SENSOR_ATTR_TEMP(16, 15), -}; - -#define THERMAL_ATTRS(X) \ - &sensor_dev_attr_thermal_temp_input[X].dev_attr.attr +#define THERMAL_ATTRS(X) \ + &sensor_dev_attr_thermal_temp_input[X].dev_attr.attr static struct attribute *thermal_temp_input_attr[] = { THERMAL_ATTRS(8), @@ -3907,13 +2845,12 @@ static int __init thermal_init(struct ibm_init_struct *iibm) if (ta1 == 0) { /* This is sheer paranoia, but we handle it anyway */ if (acpi_tmp7) { - printk(TPACPI_ERR + printk(IBM_ERR "ThinkPad ACPI EC access misbehaving, " - "falling back to ACPI TMPx access " - "mode\n"); + "falling back to ACPI TMPx access mode\n"); thermal_read_mode = TPACPI_THERMAL_ACPI_TMP07; } else { - printk(TPACPI_ERR + printk(IBM_ERR "ThinkPad ACPI EC access misbehaving, " "disabling thermal sensors access\n"); thermal_read_mode = TPACPI_THERMAL_NONE; @@ -3940,7 +2877,7 @@ static int __init thermal_init(struct ibm_init_struct *iibm) str_supported(thermal_read_mode != TPACPI_THERMAL_NONE), thermal_read_mode); - switch (thermal_read_mode) { + switch(thermal_read_mode) { case TPACPI_THERMAL_TPEC_16: res = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj, &thermal_temp_input16_group); @@ -3965,7 +2902,7 @@ static int __init thermal_init(struct ibm_init_struct *iibm) static void thermal_exit(void) { - switch (thermal_read_mode) { + switch(thermal_read_mode) { case TPACPI_THERMAL_TPEC_16: sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj, &thermal_temp_input16_group); @@ -3982,6 +2919,88 @@ static void thermal_exit(void) } } +/* idx is zero-based */ +static int thermal_get_sensor(int idx, s32 *value) +{ + int t; + s8 tmp; + char tmpi[5]; + + t = TP_EC_THERMAL_TMP0; + + switch (thermal_read_mode) { +#if TPACPI_MAX_THERMAL_SENSORS >= 16 + case TPACPI_THERMAL_TPEC_16: + if (idx >= 8 && idx <= 15) { + t = TP_EC_THERMAL_TMP8; + idx -= 8; + } + /* fallthrough */ +#endif + case TPACPI_THERMAL_TPEC_8: + if (idx <= 7) { + if (!acpi_ec_read(t + idx, &tmp)) + return -EIO; + *value = tmp * 1000; + return 0; + } + break; + + case TPACPI_THERMAL_ACPI_UPDT: + if (idx <= 7) { + snprintf(tmpi, sizeof(tmpi), "TMP%c", '0' + idx); + if (!acpi_evalf(ec_handle, NULL, "UPDT", "v")) + return -EIO; + if (!acpi_evalf(ec_handle, &t, tmpi, "d")) + return -EIO; + *value = (t - 2732) * 100; + return 0; + } + break; + + case TPACPI_THERMAL_ACPI_TMP07: + if (idx <= 7) { + snprintf(tmpi, sizeof(tmpi), "TMP%c", '0' + idx); + if (!acpi_evalf(ec_handle, &t, tmpi, "d")) + return -EIO; + if (t > 127 || t < -127) + t = TP_EC_THERMAL_TMP_NA; + *value = t * 1000; + return 0; + } + break; + + case TPACPI_THERMAL_NONE: + default: + return -ENOSYS; + } + + return -EINVAL; +} + +static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s) +{ + int res, i; + int n; + + n = 8; + i = 0; + + if (!s) + return -EINVAL; + + if (thermal_read_mode == TPACPI_THERMAL_TPEC_16) + n = 16; + + for(i = 0 ; i < n; i++) { + res = thermal_get_sensor(i, &s->temp[i]); + if (res) + return res; + } + + return n; +} + static int thermal_read(char *p) { int len = 0; @@ -4084,168 +3103,71 @@ static struct ibm_struct ecdump_driver_data = { * Backlight/brightness subdriver */ -#define TPACPI_BACKLIGHT_DEV_NAME "thinkpad_screen" - static struct backlight_device *ibm_backlight_device; -static int brightness_offset = 0x31; -static int brightness_mode; -static unsigned int brightness_enable = 2; /* 2 = auto, 0 = no, 1 = yes */ + +static struct backlight_ops ibm_backlight_data = { + .get_brightness = brightness_get, + .update_status = brightness_update_status, +}; static struct mutex brightness_mutex; -/* - * ThinkPads can read brightness from two places: EC 0x31, or - * CMOS NVRAM byte 0x5E, bits 0-3. - */ -static int brightness_get(struct backlight_device *bd) +static int __init tpacpi_query_bcll_levels(acpi_handle handle) { - u8 lec = 0, lcmos = 0, level = 0; - - if (brightness_mode & 1) { - if (!acpi_ec_read(brightness_offset, &lec)) - return -EIO; - lec &= (tp_features.bright_16levels)? 0x0f : 0x07; - level = lec; - }; - if (brightness_mode & 2) { - lcmos = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS) - & TP_NVRAM_MASK_LEVEL_BRIGHTNESS) - >> TP_NVRAM_POS_LEVEL_BRIGHTNESS; - lcmos &= (tp_features.bright_16levels)? 0x0f : 0x07; - level = lcmos; - } + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *obj; + int rc; - if (brightness_mode == 3 && lec != lcmos) { - printk(TPACPI_ERR - "CMOS NVRAM (%u) and EC (%u) do not agree " - "on display brightness level\n", - (unsigned int) lcmos, - (unsigned int) lec); - return -EIO; + if (ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buffer))) { + obj = (union acpi_object *)buffer.pointer; + if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) { + printk(IBM_ERR "Unknown BCLL data, " + "please report this to %s\n", IBM_MAIL); + rc = 0; + } else { + rc = obj->package.count; + } + } else { + return 0; } - return level; + kfree(buffer.pointer); + return rc; } -/* May return EINTR which can always be mapped to ERESTARTSYS */ -static int brightness_set(int value) +static acpi_status __init brightness_find_bcll(acpi_handle handle, u32 lvl, + void *context, void **rv) { - int cmos_cmd, inc, i, res; - int current_value; + char name[ACPI_PATH_SEGMENT_LENGTH]; + struct acpi_buffer buffer = { sizeof(name), &name }; - if (value > ((tp_features.bright_16levels)? 15 : 7)) - return -EINVAL; + if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) && + !strncmp("BCLL", name, sizeof(name) - 1)) { + if (tpacpi_query_bcll_levels(handle) == 16) { + *rv = handle; + return AE_CTRL_TERMINATE; + } else { + return AE_OK; + } + } else { + return AE_OK; + } +} - res = mutex_lock_interruptible(&brightness_mutex); - if (res < 0) - return res; +static int __init brightness_check_levels(void) +{ + int status; + void *found_node = NULL; - current_value = brightness_get(NULL); - if (current_value < 0) { - res = current_value; - goto errout; + if (!vid_handle) { + IBM_ACPIHANDLE_INIT(vid); } - - cmos_cmd = value > current_value ? - TP_CMOS_BRIGHTNESS_UP : - TP_CMOS_BRIGHTNESS_DOWN; - inc = (value > current_value)? 1 : -1; - - res = 0; - for (i = current_value; i != value; i += inc) { - if ((brightness_mode & 2) && - issue_thinkpad_cmos_command(cmos_cmd)) { - res = -EIO; - goto errout; - } - if ((brightness_mode & 1) && - !acpi_ec_write(brightness_offset, i + inc)) { - res = -EIO; - goto errout;; - } - } - -errout: - mutex_unlock(&brightness_mutex); - return res; -} - -/* sysfs backlight class ----------------------------------------------- */ - -static int brightness_update_status(struct backlight_device *bd) -{ - /* it is the backlight class's job (caller) to handle - * EINTR and other errors properly */ - return brightness_set( - (bd->props.fb_blank == FB_BLANK_UNBLANK && - bd->props.power == FB_BLANK_UNBLANK) ? - bd->props.brightness : 0); -} - -static struct backlight_ops ibm_backlight_data = { - .get_brightness = brightness_get, - .update_status = brightness_update_status, -}; - -/* --------------------------------------------------------------------- */ - -static int __init tpacpi_query_bcll_levels(acpi_handle handle) -{ - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *obj; - int rc; - - if (ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buffer))) { - obj = (union acpi_object *)buffer.pointer; - if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) { - printk(TPACPI_ERR "Unknown BCLL data, " - "please report this to %s\n", TPACPI_MAIL); - rc = 0; - } else { - rc = obj->package.count; - } - } else { - return 0; - } - - kfree(buffer.pointer); - return rc; -} - -static acpi_status __init brightness_find_bcll(acpi_handle handle, u32 lvl, - void *context, void **rv) -{ - char name[ACPI_PATH_SEGMENT_LENGTH]; - struct acpi_buffer buffer = { sizeof(name), &name }; - - if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) && - !strncmp("BCLL", name, sizeof(name) - 1)) { - if (tpacpi_query_bcll_levels(handle) == 16) { - *rv = handle; - return AE_CTRL_TERMINATE; - } else { - return AE_OK; - } - } else { - return AE_OK; - } -} - -static int __init brightness_check_levels(void) -{ - int status; - void *found_node = NULL; - - if (!vid_handle) { - TPACPI_ACPIHANDLE_INIT(vid); - } - if (!vid_handle) - return 0; + if (!vid_handle) + return 0; /* Search for a BCLL package with 16 levels */ status = acpi_walk_namespace(ACPI_TYPE_PACKAGE, vid_handle, 3, - brightness_find_bcll, NULL, - &found_node); + brightness_find_bcll, NULL, &found_node); return (ACPI_SUCCESS(status) && found_node != NULL); } @@ -4271,14 +3193,14 @@ static int __init brightness_check_std_acpi_support(void) void *found_node = NULL; if (!vid_handle) { - TPACPI_ACPIHANDLE_INIT(vid); + IBM_ACPIHANDLE_INIT(vid); } if (!vid_handle) return 0; /* Search for a _BCL method, but don't execute it */ status = acpi_walk_namespace(ACPI_TYPE_METHOD, vid_handle, 3, - brightness_find_bcl, NULL, &found_node); + brightness_find_bcl, NULL, &found_node); return (ACPI_SUCCESS(status) && found_node != NULL); } @@ -4293,14 +3215,12 @@ static int __init brightness_init(struct ibm_init_struct *iibm) if (!brightness_enable) { dbg_printk(TPACPI_DBG_INIT, - "brightness support disabled by " - "module parameter\n"); + "brightness support disabled by module parameter\n"); return 1; } else if (brightness_enable > 1) { if (brightness_check_std_acpi_support()) { - printk(TPACPI_NOTICE - "standard ACPI backlight interface " - "available, not loading native one...\n"); + printk(IBM_NOTICE + "standard ACPI backlight interface available, not loading native one...\n"); return 1; } } @@ -4327,14 +3247,13 @@ static int __init brightness_init(struct ibm_init_struct *iibm) return 1; if (tp_features.bright_16levels) - printk(TPACPI_INFO - "detected a 16-level brightness capable ThinkPad\n"); + printk(IBM_INFO "detected a 16-level brightness capable ThinkPad\n"); ibm_backlight_device = backlight_device_register( TPACPI_BACKLIGHT_DEV_NAME, NULL, NULL, &ibm_backlight_data); if (IS_ERR(ibm_backlight_device)) { - printk(TPACPI_ERR "Could not register backlight device\n"); + printk(IBM_ERR "Could not register backlight device\n"); return PTR_ERR(ibm_backlight_device); } vdbg_printk(TPACPI_DBG_INIT, "brightness is supported\n"); @@ -4357,13 +3276,99 @@ static void brightness_exit(void) } } +static int brightness_update_status(struct backlight_device *bd) +{ + /* it is the backlight class's job (caller) to handle + * EINTR and other errors properly */ + return brightness_set( + (bd->props.fb_blank == FB_BLANK_UNBLANK && + bd->props.power == FB_BLANK_UNBLANK) ? + bd->props.brightness : 0); +} + +/* + * ThinkPads can read brightness from two places: EC 0x31, or + * CMOS NVRAM byte 0x5E, bits 0-3. + */ +static int brightness_get(struct backlight_device *bd) +{ + u8 lec = 0, lcmos = 0, level = 0; + + if (brightness_mode & 1) { + if (!acpi_ec_read(brightness_offset, &lec)) + return -EIO; + lec &= (tp_features.bright_16levels)? 0x0f : 0x07; + level = lec; + }; + if (brightness_mode & 2) { + lcmos = (nvram_read_byte(TP_NVRAM_ADDR_BRIGHTNESS) + & TP_NVRAM_MASK_LEVEL_BRIGHTNESS) + >> TP_NVRAM_POS_LEVEL_BRIGHTNESS; + lcmos &= (tp_features.bright_16levels)? 0x0f : 0x07; + level = lcmos; + } + + if (brightness_mode == 3 && lec != lcmos) { + printk(IBM_ERR + "CMOS NVRAM (%u) and EC (%u) do not agree " + "on display brightness level\n", + (unsigned int) lcmos, + (unsigned int) lec); + return -EIO; + } + + return level; +} + +/* May return EINTR which can always be mapped to ERESTARTSYS */ +static int brightness_set(int value) +{ + int cmos_cmd, inc, i, res; + int current_value; + + if (value > ((tp_features.bright_16levels)? 15 : 7)) + return -EINVAL; + + res = mutex_lock_interruptible(&brightness_mutex); + if (res < 0) + return res; + + current_value = brightness_get(NULL); + if (current_value < 0) { + res = current_value; + goto errout; + } + + cmos_cmd = value > current_value ? + TP_CMOS_BRIGHTNESS_UP : + TP_CMOS_BRIGHTNESS_DOWN; + inc = (value > current_value)? 1 : -1; + + res = 0; + for (i = current_value; i != value; i += inc) { + if ((brightness_mode & 2) && + issue_thinkpad_cmos_command(cmos_cmd)) { + res = -EIO; + goto errout; + } + if ((brightness_mode & 1) && + !acpi_ec_write(brightness_offset, i + inc)) { + res = -EIO; + goto errout;; + } + } + +errout: + mutex_unlock(&brightness_mutex); + return res; +} + static int brightness_read(char *p) { int len = 0; int level; - level = brightness_get(NULL); - if (level < 0) { + if ((level = brightness_get(NULL)) < 0) { len += sprintf(p + len, "level:\t\tunreadable\n"); } else { len += sprintf(p + len, "level:\t\t%d\n", level); @@ -4420,8 +3425,6 @@ static struct ibm_struct brightness_driver_data = { * Volume subdriver */ -static int volume_offset = 0x30; - static int volume_read(char *p) { int len = 0; @@ -4471,11 +3474,8 @@ static int volume_write(char *buf) } else return -EINVAL; - if (new_level != level) { - /* mute doesn't change */ - - cmos_cmd = (new_level > level) ? - TP_CMOS_VOLUME_UP : TP_CMOS_VOLUME_DOWN; + if (new_level != level) { /* mute doesn't change */ + cmos_cmd = new_level > level ? TP_CMOS_VOLUME_UP : TP_CMOS_VOLUME_DOWN; inc = new_level > level ? 1 : -1; if (mute && (issue_thinkpad_cmos_command(cmos_cmd) || @@ -4487,18 +3487,14 @@ static int volume_write(char *buf) !acpi_ec_write(volume_offset, i + inc)) return -EIO; - if (mute && - (issue_thinkpad_cmos_command(TP_CMOS_VOLUME_MUTE) || - !acpi_ec_write(volume_offset, new_level + mute))) { + if (mute && (issue_thinkpad_cmos_command(TP_CMOS_VOLUME_MUTE) || + !acpi_ec_write(volume_offset, + new_level + mute))) return -EIO; - } } - if (new_mute != mute) { - /* level doesn't change */ - - cmos_cmd = (new_mute) ? - TP_CMOS_VOLUME_MUTE : TP_CMOS_VOLUME_UP; + if (new_mute != mute) { /* level doesn't change */ + cmos_cmd = new_mute ? TP_CMOS_VOLUME_MUTE : TP_CMOS_VOLUME_UP; if (issue_thinkpad_cmos_command(cmos_cmd) || !acpi_ec_write(volume_offset, level + new_mute)) @@ -4620,333 +3616,478 @@ static struct ibm_struct volume_driver_data = { * but the ACPI tables just mention level 7. */ -enum { /* Fan control constants */ - fan_status_offset = 0x2f, /* EC register 0x2f */ - fan_rpm_offset = 0x84, /* EC register 0x84: LSB, 0x85 MSB (RPM) - * 0x84 must be read before 0x85 */ - - TP_EC_FAN_FULLSPEED = 0x40, /* EC fan mode: full speed */ - TP_EC_FAN_AUTO = 0x80, /* EC fan mode: auto fan control */ - - TPACPI_FAN_LAST_LEVEL = 0x100, /* Use cached last-seen fan level */ -}; - -enum fan_status_access_mode { - TPACPI_FAN_NONE = 0, /* No fan status or control */ - TPACPI_FAN_RD_ACPI_GFAN, /* Use ACPI GFAN */ - TPACPI_FAN_RD_TPEC, /* Use ACPI EC regs 0x2f, 0x84-0x85 */ -}; - -enum fan_control_access_mode { - TPACPI_FAN_WR_NONE = 0, /* No fan control */ - TPACPI_FAN_WR_ACPI_SFAN, /* Use ACPI SFAN */ - TPACPI_FAN_WR_TPEC, /* Use ACPI EC reg 0x2f */ - TPACPI_FAN_WR_ACPI_FANS, /* Use ACPI FANS and EC reg 0x2f */ -}; - -enum fan_control_commands { - TPACPI_FAN_CMD_SPEED = 0x0001, /* speed command */ - TPACPI_FAN_CMD_LEVEL = 0x0002, /* level command */ - TPACPI_FAN_CMD_ENABLE = 0x0004, /* enable/disable cmd, - * and also watchdog cmd */ -}; - -static int fan_control_allowed; - static enum fan_status_access_mode fan_status_access_mode; static enum fan_control_access_mode fan_control_access_mode; static enum fan_control_commands fan_control_commands; static u8 fan_control_initial_status; static u8 fan_control_desired_level; -static int fan_watchdog_maxinterval; - -static struct mutex fan_mutex; static void fan_watchdog_fire(struct work_struct *ignored); +static int fan_watchdog_maxinterval; static DECLARE_DELAYED_WORK(fan_watchdog_task, fan_watchdog_fire); -TPACPI_HANDLE(fans, ec, "FANS"); /* X31, X40, X41 */ -TPACPI_HANDLE(gfan, ec, "GFAN", /* 570 */ +IBM_HANDLE(fans, ec, "FANS"); /* X31, X40, X41 */ +IBM_HANDLE(gfan, ec, "GFAN", /* 570 */ "\\FSPD", /* 600e/x, 770e, 770x */ ); /* all others */ -TPACPI_HANDLE(sfan, ec, "SFAN", /* 570 */ +IBM_HANDLE(sfan, ec, "SFAN", /* 570 */ "JFNS", /* 770x-JL */ ); /* all others */ /* - * Call with fan_mutex held + * SYSFS fan layout: hwmon compatible (device) + * + * pwm*_enable: + * 0: "disengaged" mode + * 1: manual mode + * 2: native EC "auto" mode (recommended, hardware default) + * + * pwm*: set speed in manual mode, ignored otherwise. + * 0 is level 0; 255 is level 7. Intermediate points done with linear + * interpolation. + * + * fan*_input: tachometer reading, RPM + * + * + * SYSFS fan layout: extensions + * + * fan_watchdog (driver): + * fan watchdog interval in seconds, 0 disables (default), max 120 */ -static void fan_update_desired_level(u8 status) -{ - if ((status & - (TP_EC_FAN_AUTO | TP_EC_FAN_FULLSPEED)) == 0) { - if (status > 7) - fan_control_desired_level = 7; - else - fan_control_desired_level = status; - } -} -static int fan_get_status(u8 *status) +/* sysfs fan pwm1_enable ----------------------------------------------- */ +static ssize_t fan_pwm1_enable_show(struct device *dev, + struct device_attribute *attr, + char *buf) { - u8 s; + int res, mode; + u8 status; - /* TODO: - * Add TPACPI_FAN_RD_ACPI_FANS ? */ + res = fan_get_status_safe(&status); + if (res) + return res; - switch (fan_status_access_mode) { - case TPACPI_FAN_RD_ACPI_GFAN: - /* 570, 600e/x, 770e, 770x */ + if (unlikely(tp_features.fan_ctrl_status_undef)) { + if (status != fan_control_initial_status) { + tp_features.fan_ctrl_status_undef = 0; + } else { + /* Return most likely status. In fact, it + * might be the only possible status */ + status = TP_EC_FAN_AUTO; + } + } - if (unlikely(!acpi_evalf(gfan_handle, &s, NULL, "d"))) - return -EIO; + if (status & TP_EC_FAN_FULLSPEED) { + mode = 0; + } else if (status & TP_EC_FAN_AUTO) { + mode = 2; + } else + mode = 1; - if (likely(status)) - *status = s & 0x07; - - break; + return snprintf(buf, PAGE_SIZE, "%d\n", mode); +} - case TPACPI_FAN_RD_TPEC: - /* all except 570, 600e/x, 770e, 770x */ - if (unlikely(!acpi_ec_read(fan_status_offset, &s))) - return -EIO; +static ssize_t fan_pwm1_enable_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned long t; + int res, level; - if (likely(status)) - *status = s; + if (parse_strtoul(buf, 2, &t)) + return -EINVAL; + switch (t) { + case 0: + level = TP_EC_FAN_FULLSPEED; break; - + case 1: + level = TPACPI_FAN_LAST_LEVEL; + break; + case 2: + level = TP_EC_FAN_AUTO; + break; + case 3: + /* reserved for software-controlled auto mode */ + return -ENOSYS; default: - return -ENXIO; + return -EINVAL; } - return 0; + res = fan_set_level_safe(level); + if (res == -ENXIO) + return -EINVAL; + else if (res < 0) + return res; + + fan_watchdog_reset(); + + return count; } -static int fan_get_status_safe(u8 *status) +static struct device_attribute dev_attr_fan_pwm1_enable = + __ATTR(pwm1_enable, S_IWUSR | S_IRUGO, + fan_pwm1_enable_show, fan_pwm1_enable_store); + +/* sysfs fan pwm1 ------------------------------------------------------ */ +static ssize_t fan_pwm1_show(struct device *dev, + struct device_attribute *attr, + char *buf) { - int rc; - u8 s; + int res; + u8 status; - if (mutex_lock_interruptible(&fan_mutex)) - return -ERESTARTSYS; - rc = fan_get_status(&s); - if (!rc) - fan_update_desired_level(s); - mutex_unlock(&fan_mutex); + res = fan_get_status_safe(&status); + if (res) + return res; - if (status) - *status = s; + if (unlikely(tp_features.fan_ctrl_status_undef)) { + if (status != fan_control_initial_status) { + tp_features.fan_ctrl_status_undef = 0; + } else { + status = TP_EC_FAN_AUTO; + } + } - return rc; + if ((status & + (TP_EC_FAN_AUTO | TP_EC_FAN_FULLSPEED)) != 0) + status = fan_control_desired_level; + + if (status > 7) + status = 7; + + return snprintf(buf, PAGE_SIZE, "%u\n", (status * 255) / 7); } -static int fan_get_speed(unsigned int *speed) +static ssize_t fan_pwm1_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { - u8 hi, lo; + unsigned long s; + int rc; + u8 status, newlevel; - switch (fan_status_access_mode) { - case TPACPI_FAN_RD_TPEC: - /* all except 570, 600e/x, 770e, 770x */ - if (unlikely(!acpi_ec_read(fan_rpm_offset, &lo) || - !acpi_ec_read(fan_rpm_offset + 1, &hi))) - return -EIO; + if (parse_strtoul(buf, 255, &s)) + return -EINVAL; - if (likely(speed)) - *speed = (hi << 8) | lo; + /* scale down from 0-255 to 0-7 */ + newlevel = (s >> 5) & 0x07; - break; + if (mutex_lock_interruptible(&fan_mutex)) + return -ERESTARTSYS; - default: - return -ENXIO; + rc = fan_get_status(&status); + if (!rc && (status & + (TP_EC_FAN_AUTO | TP_EC_FAN_FULLSPEED)) == 0) { + rc = fan_set_level(newlevel); + if (rc == -ENXIO) + rc = -EINVAL; + else if (!rc) { + fan_update_desired_level(newlevel); + fan_watchdog_reset(); + } } - return 0; + mutex_unlock(&fan_mutex); + return (rc)? rc : count; } -static int fan_set_level(int level) -{ - if (!fan_control_allowed) - return -EPERM; +static struct device_attribute dev_attr_fan_pwm1 = + __ATTR(pwm1, S_IWUSR | S_IRUGO, + fan_pwm1_show, fan_pwm1_store); - switch (fan_control_access_mode) { - case TPACPI_FAN_WR_ACPI_SFAN: - if (level >= 0 && level <= 7) { - if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", level)) - return -EIO; - } else - return -EINVAL; - break; +/* sysfs fan fan1_input ------------------------------------------------ */ +static ssize_t fan_fan1_input_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + int res; + unsigned int speed; - case TPACPI_FAN_WR_ACPI_FANS: - case TPACPI_FAN_WR_TPEC: - if ((level != TP_EC_FAN_AUTO) && - (level != TP_EC_FAN_FULLSPEED) && - ((level < 0) || (level > 7))) - return -EINVAL; + res = fan_get_speed(&speed); + if (res < 0) + return res; - /* safety net should the EC not support AUTO - * or FULLSPEED mode bits and just ignore them */ - if (level & TP_EC_FAN_FULLSPEED) - level |= 7; /* safety min speed 7 */ - else if (level & TP_EC_FAN_AUTO) - level |= 4; /* safety min speed 4 */ + return snprintf(buf, PAGE_SIZE, "%u\n", speed); +} - if (!acpi_ec_write(fan_status_offset, level)) - return -EIO; - else - tp_features.fan_ctrl_status_undef = 0; - break; +static struct device_attribute dev_attr_fan_fan1_input = + __ATTR(fan1_input, S_IRUGO, + fan_fan1_input_show, NULL); - default: - return -ENXIO; - } - return 0; +/* sysfs fan fan_watchdog (hwmon driver) ------------------------------- */ +static ssize_t fan_fan_watchdog_show(struct device_driver *drv, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", fan_watchdog_maxinterval); } -static int fan_set_level_safe(int level) +static ssize_t fan_fan_watchdog_store(struct device_driver *drv, + const char *buf, size_t count) { - int rc; + unsigned long t; + + if (parse_strtoul(buf, 120, &t)) + return -EINVAL; if (!fan_control_allowed) return -EPERM; - if (mutex_lock_interruptible(&fan_mutex)) - return -ERESTARTSYS; + fan_watchdog_maxinterval = t; + fan_watchdog_reset(); - if (level == TPACPI_FAN_LAST_LEVEL) - level = fan_control_desired_level; + return count; +} - rc = fan_set_level(level); - if (!rc) - fan_update_desired_level(level); +static DRIVER_ATTR(fan_watchdog, S_IWUSR | S_IRUGO, + fan_fan_watchdog_show, fan_fan_watchdog_store); - mutex_unlock(&fan_mutex); - return rc; -} +/* --------------------------------------------------------------------- */ +static struct attribute *fan_attributes[] = { + &dev_attr_fan_pwm1_enable.attr, &dev_attr_fan_pwm1.attr, + &dev_attr_fan_fan1_input.attr, + NULL +}; -static int fan_set_enable(void) +static const struct attribute_group fan_attr_group = { + .attrs = fan_attributes, +}; + +static int __init fan_init(struct ibm_init_struct *iibm) { - u8 s; int rc; - if (!fan_control_allowed) - return -EPERM; - - if (mutex_lock_interruptible(&fan_mutex)) - return -ERESTARTSYS; + vdbg_printk(TPACPI_DBG_INIT, "initializing fan subdriver\n"); - switch (fan_control_access_mode) { - case TPACPI_FAN_WR_ACPI_FANS: - case TPACPI_FAN_WR_TPEC: - rc = fan_get_status(&s); - if (rc < 0) - break; + mutex_init(&fan_mutex); + fan_status_access_mode = TPACPI_FAN_NONE; + fan_control_access_mode = TPACPI_FAN_WR_NONE; + fan_control_commands = 0; + fan_watchdog_maxinterval = 0; + tp_features.fan_ctrl_status_undef = 0; + fan_control_desired_level = 7; - /* Don't go out of emergency fan mode */ - if (s != 7) { - s &= 0x07; - s |= TP_EC_FAN_AUTO | 4; /* min fan speed 4 */ - } + IBM_ACPIHANDLE_INIT(fans); + IBM_ACPIHANDLE_INIT(gfan); + IBM_ACPIHANDLE_INIT(sfan); - if (!acpi_ec_write(fan_status_offset, s)) - rc = -EIO; - else { - tp_features.fan_ctrl_status_undef = 0; - rc = 0; - } - break; + if (gfan_handle) { + /* 570, 600e/x, 770e, 770x */ + fan_status_access_mode = TPACPI_FAN_RD_ACPI_GFAN; + } else { + /* all other ThinkPads: note that even old-style + * ThinkPad ECs supports the fan control register */ + if (likely(acpi_ec_read(fan_status_offset, + &fan_control_initial_status))) { + fan_status_access_mode = TPACPI_FAN_RD_TPEC; - case TPACPI_FAN_WR_ACPI_SFAN: - rc = fan_get_status(&s); - if (rc < 0) - break; + /* In some ThinkPads, neither the EC nor the ACPI + * DSDT initialize the fan status, and it ends up + * being set to 0x07 when it *could* be either + * 0x07 or 0x80. + * + * Enable for TP-1Y (T43), TP-78 (R51e), + * TP-76 (R52), TP-70 (T43, R52), which are known + * to be buggy. */ + if (fan_control_initial_status == 0x07) { + switch (thinkpad_id.ec_model) { + case 0x5931: /* TP-1Y */ + case 0x3837: /* TP-78 */ + case 0x3637: /* TP-76 */ + case 0x3037: /* TP-70 */ + printk(IBM_NOTICE + "fan_init: initial fan status is " + "unknown, assuming it is in auto " + "mode\n"); + tp_features.fan_ctrl_status_undef = 1; + ;; + } + } + } else { + printk(IBM_ERR + "ThinkPad ACPI EC access misbehaving, " + "fan status and control unavailable\n"); + return 1; + } + } - s &= 0x07; + if (sfan_handle) { + /* 570, 770x-JL */ + fan_control_access_mode = TPACPI_FAN_WR_ACPI_SFAN; + fan_control_commands |= + TPACPI_FAN_CMD_LEVEL | TPACPI_FAN_CMD_ENABLE; + } else { + if (!gfan_handle) { + /* gfan without sfan means no fan control */ + /* all other models implement TP EC 0x2f control */ - /* Set fan to at least level 4 */ - s |= 4; + if (fans_handle) { + /* X31, X40, X41 */ + fan_control_access_mode = + TPACPI_FAN_WR_ACPI_FANS; + fan_control_commands |= + TPACPI_FAN_CMD_SPEED | + TPACPI_FAN_CMD_LEVEL | + TPACPI_FAN_CMD_ENABLE; + } else { + fan_control_access_mode = TPACPI_FAN_WR_TPEC; + fan_control_commands |= + TPACPI_FAN_CMD_LEVEL | + TPACPI_FAN_CMD_ENABLE; + } + } + } - if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", s)) - rc = -EIO; - else - rc = 0; - break; + vdbg_printk(TPACPI_DBG_INIT, "fan is %s, modes %d, %d\n", + str_supported(fan_status_access_mode != TPACPI_FAN_NONE || + fan_control_access_mode != TPACPI_FAN_WR_NONE), + fan_status_access_mode, fan_control_access_mode); - default: - rc = -ENXIO; + /* fan control master switch */ + if (!fan_control_allowed) { + fan_control_access_mode = TPACPI_FAN_WR_NONE; + fan_control_commands = 0; + dbg_printk(TPACPI_DBG_INIT, + "fan control features disabled by parameter\n"); } - mutex_unlock(&fan_mutex); - return rc; + /* update fan_control_desired_level */ + if (fan_status_access_mode != TPACPI_FAN_NONE) + fan_get_status_safe(NULL); + + if (fan_status_access_mode != TPACPI_FAN_NONE || + fan_control_access_mode != TPACPI_FAN_WR_NONE) { + rc = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj, + &fan_attr_group); + if (!(rc < 0)) + rc = driver_create_file(&tpacpi_hwmon_pdriver.driver, + &driver_attr_fan_watchdog); + if (rc < 0) + return rc; + return 0; + } else + return 1; } -static int fan_set_disable(void) +/* + * Call with fan_mutex held + */ +static void fan_update_desired_level(u8 status) { - int rc; + if ((status & + (TP_EC_FAN_AUTO | TP_EC_FAN_FULLSPEED)) == 0) { + if (status > 7) + fan_control_desired_level = 7; + else + fan_control_desired_level = status; + } +} - if (!fan_control_allowed) - return -EPERM; +static int fan_get_status(u8 *status) +{ + u8 s; - if (mutex_lock_interruptible(&fan_mutex)) - return -ERESTARTSYS; + /* TODO: + * Add TPACPI_FAN_RD_ACPI_FANS ? */ + + switch (fan_status_access_mode) { + case TPACPI_FAN_RD_ACPI_GFAN: + /* 570, 600e/x, 770e, 770x */ + + if (unlikely(!acpi_evalf(gfan_handle, &s, NULL, "d"))) + return -EIO; + + if (likely(status)) + *status = s & 0x07; - rc = 0; - switch (fan_control_access_mode) { - case TPACPI_FAN_WR_ACPI_FANS: - case TPACPI_FAN_WR_TPEC: - if (!acpi_ec_write(fan_status_offset, 0x00)) - rc = -EIO; - else { - fan_control_desired_level = 0; - tp_features.fan_ctrl_status_undef = 0; - } break; - case TPACPI_FAN_WR_ACPI_SFAN: - if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", 0x00)) - rc = -EIO; - else - fan_control_desired_level = 0; + case TPACPI_FAN_RD_TPEC: + /* all except 570, 600e/x, 770e, 770x */ + if (unlikely(!acpi_ec_read(fan_status_offset, &s))) + return -EIO; + + if (likely(status)) + *status = s; + break; default: - rc = -ENXIO; + return -ENXIO; } + return 0; +} + +static int fan_get_status_safe(u8 *status) +{ + int rc; + u8 s; + if (mutex_lock_interruptible(&fan_mutex)) + return -ERESTARTSYS; + rc = fan_get_status(&s); + if (!rc) + fan_update_desired_level(s); mutex_unlock(&fan_mutex); + + if (status) + *status = s; + return rc; } -static int fan_set_speed(int speed) +static void fan_exit(void) { - int rc; + vdbg_printk(TPACPI_DBG_EXIT, "cancelling any pending fan watchdog tasks\n"); - if (!fan_control_allowed) - return -EPERM; + /* FIXME: can we really do this unconditionally? */ + sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj, &fan_attr_group); + driver_remove_file(&tpacpi_hwmon_pdriver.driver, &driver_attr_fan_watchdog); - if (mutex_lock_interruptible(&fan_mutex)) - return -ERESTARTSYS; + cancel_delayed_work(&fan_watchdog_task); + flush_scheduled_work(); +} + +static int fan_get_speed(unsigned int *speed) +{ + u8 hi, lo; + + switch (fan_status_access_mode) { + case TPACPI_FAN_RD_TPEC: + /* all except 570, 600e/x, 770e, 770x */ + if (unlikely(!acpi_ec_read(fan_rpm_offset, &lo) || + !acpi_ec_read(fan_rpm_offset + 1, &hi))) + return -EIO; + + if (likely(speed)) + *speed = (hi << 8) | lo; - rc = 0; - switch (fan_control_access_mode) { - case TPACPI_FAN_WR_ACPI_FANS: - if (speed >= 0 && speed <= 65535) { - if (!acpi_evalf(fans_handle, NULL, NULL, "vddd", - speed, speed, speed)) - rc = -EIO; - } else - rc = -EINVAL; break; default: - rc = -ENXIO; + return -ENXIO; } - mutex_unlock(&fan_mutex); - return rc; + return 0; +} + +static void fan_watchdog_fire(struct work_struct *ignored) +{ + int rc; + + if (tpacpi_lifecycle != TPACPI_LIFE_RUNNING) + return; + + printk(IBM_NOTICE "fan watchdog: enabling fan\n"); + rc = fan_set_enable(); + if (rc < 0) { + printk(IBM_ERR "fan watchdog: error %d while enabling fan, " + "will try again later...\n", -rc); + /* reschedule for later */ + fan_watchdog_reset(); + } } static void fan_watchdog_reset(void) @@ -4965,378 +4106,195 @@ static void fan_watchdog_reset(void) if (!schedule_delayed_work(&fan_watchdog_task, msecs_to_jiffies(fan_watchdog_maxinterval * 1000))) { - printk(TPACPI_ERR - "failed to schedule the fan watchdog, " + printk(IBM_ERR "failed to schedule the fan watchdog, " "watchdog will not trigger\n"); } } else fan_watchdog_active = 0; } -static void fan_watchdog_fire(struct work_struct *ignored) +static int fan_set_level(int level) { - int rc; + if (!fan_control_allowed) + return -EPERM; - if (tpacpi_lifecycle != TPACPI_LIFE_RUNNING) - return; + switch (fan_control_access_mode) { + case TPACPI_FAN_WR_ACPI_SFAN: + if (level >= 0 && level <= 7) { + if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", level)) + return -EIO; + } else + return -EINVAL; + break; - printk(TPACPI_NOTICE "fan watchdog: enabling fan\n"); - rc = fan_set_enable(); - if (rc < 0) { - printk(TPACPI_ERR "fan watchdog: error %d while enabling fan, " - "will try again later...\n", -rc); - /* reschedule for later */ - fan_watchdog_reset(); - } -} + case TPACPI_FAN_WR_ACPI_FANS: + case TPACPI_FAN_WR_TPEC: + if ((level != TP_EC_FAN_AUTO) && + (level != TP_EC_FAN_FULLSPEED) && + ((level < 0) || (level > 7))) + return -EINVAL; -/* - * SYSFS fan layout: hwmon compatible (device) - * - * pwm*_enable: - * 0: "disengaged" mode - * 1: manual mode - * 2: native EC "auto" mode (recommended, hardware default) - * - * pwm*: set speed in manual mode, ignored otherwise. - * 0 is level 0; 255 is level 7. Intermediate points done with linear - * interpolation. - * - * fan*_input: tachometer reading, RPM - * - * - * SYSFS fan layout: extensions - * - * fan_watchdog (driver): - * fan watchdog interval in seconds, 0 disables (default), max 120 - */ - -/* sysfs fan pwm1_enable ----------------------------------------------- */ -static ssize_t fan_pwm1_enable_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int res, mode; - u8 status; - - res = fan_get_status_safe(&status); - if (res) - return res; + /* safety net should the EC not support AUTO + * or FULLSPEED mode bits and just ignore them */ + if (level & TP_EC_FAN_FULLSPEED) + level |= 7; /* safety min speed 7 */ + else if (level & TP_EC_FAN_FULLSPEED) + level |= 4; /* safety min speed 4 */ - if (unlikely(tp_features.fan_ctrl_status_undef)) { - if (status != fan_control_initial_status) { + if (!acpi_ec_write(fan_status_offset, level)) + return -EIO; + else tp_features.fan_ctrl_status_undef = 0; - } else { - /* Return most likely status. In fact, it - * might be the only possible status */ - status = TP_EC_FAN_AUTO; - } - } - - if (status & TP_EC_FAN_FULLSPEED) { - mode = 0; - } else if (status & TP_EC_FAN_AUTO) { - mode = 2; - } else - mode = 1; - - return snprintf(buf, PAGE_SIZE, "%d\n", mode); -} - -static ssize_t fan_pwm1_enable_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned long t; - int res, level; - - if (parse_strtoul(buf, 2, &t)) - return -EINVAL; - - switch (t) { - case 0: - level = TP_EC_FAN_FULLSPEED; break; - case 1: - level = TPACPI_FAN_LAST_LEVEL; - break; - case 2: - level = TP_EC_FAN_AUTO; - break; - case 3: - /* reserved for software-controlled auto mode */ - return -ENOSYS; + default: - return -EINVAL; + return -ENXIO; } - - res = fan_set_level_safe(level); - if (res == -ENXIO) - return -EINVAL; - else if (res < 0) - return res; - - fan_watchdog_reset(); - - return count; + return 0; } -static struct device_attribute dev_attr_fan_pwm1_enable = - __ATTR(pwm1_enable, S_IWUSR | S_IRUGO, - fan_pwm1_enable_show, fan_pwm1_enable_store); - -/* sysfs fan pwm1 ------------------------------------------------------ */ -static ssize_t fan_pwm1_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static int fan_set_level_safe(int level) { - int res; - u8 status; + int rc; - res = fan_get_status_safe(&status); - if (res) - return res; + if (!fan_control_allowed) + return -EPERM; - if (unlikely(tp_features.fan_ctrl_status_undef)) { - if (status != fan_control_initial_status) { - tp_features.fan_ctrl_status_undef = 0; - } else { - status = TP_EC_FAN_AUTO; - } - } + if (mutex_lock_interruptible(&fan_mutex)) + return -ERESTARTSYS; - if ((status & - (TP_EC_FAN_AUTO | TP_EC_FAN_FULLSPEED)) != 0) - status = fan_control_desired_level; + if (level == TPACPI_FAN_LAST_LEVEL) + level = fan_control_desired_level; - if (status > 7) - status = 7; + rc = fan_set_level(level); + if (!rc) + fan_update_desired_level(level); - return snprintf(buf, PAGE_SIZE, "%u\n", (status * 255) / 7); + mutex_unlock(&fan_mutex); + return rc; } -static ssize_t fan_pwm1_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static int fan_set_enable(void) { - unsigned long s; + u8 s; int rc; - u8 status, newlevel; - - if (parse_strtoul(buf, 255, &s)) - return -EINVAL; - /* scale down from 0-255 to 0-7 */ - newlevel = (s >> 5) & 0x07; + if (!fan_control_allowed) + return -EPERM; if (mutex_lock_interruptible(&fan_mutex)) return -ERESTARTSYS; - rc = fan_get_status(&status); - if (!rc && (status & - (TP_EC_FAN_AUTO | TP_EC_FAN_FULLSPEED)) == 0) { - rc = fan_set_level(newlevel); - if (rc == -ENXIO) - rc = -EINVAL; - else if (!rc) { - fan_update_desired_level(newlevel); - fan_watchdog_reset(); + switch (fan_control_access_mode) { + case TPACPI_FAN_WR_ACPI_FANS: + case TPACPI_FAN_WR_TPEC: + rc = fan_get_status(&s); + if (rc < 0) + break; + + /* Don't go out of emergency fan mode */ + if (s != 7) { + s &= 0x07; + s |= TP_EC_FAN_AUTO | 4; /* min fan speed 4 */ } - } - mutex_unlock(&fan_mutex); - return (rc)? rc : count; -} + if (!acpi_ec_write(fan_status_offset, s)) + rc = -EIO; + else { + tp_features.fan_ctrl_status_undef = 0; + rc = 0; + } + break; -static struct device_attribute dev_attr_fan_pwm1 = - __ATTR(pwm1, S_IWUSR | S_IRUGO, - fan_pwm1_show, fan_pwm1_store); + case TPACPI_FAN_WR_ACPI_SFAN: + rc = fan_get_status(&s); + if (rc < 0) + break; -/* sysfs fan fan1_input ------------------------------------------------ */ -static ssize_t fan_fan1_input_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int res; - unsigned int speed; + s &= 0x07; - res = fan_get_speed(&speed); - if (res < 0) - return res; + /* Set fan to at least level 4 */ + s |= 4; - return snprintf(buf, PAGE_SIZE, "%u\n", speed); -} + if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", s)) + rc= -EIO; + else + rc = 0; + break; -static struct device_attribute dev_attr_fan_fan1_input = - __ATTR(fan1_input, S_IRUGO, - fan_fan1_input_show, NULL); + default: + rc = -ENXIO; + } -/* sysfs fan fan_watchdog (hwmon driver) ------------------------------- */ -static ssize_t fan_fan_watchdog_show(struct device_driver *drv, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%u\n", fan_watchdog_maxinterval); + mutex_unlock(&fan_mutex); + return rc; } -static ssize_t fan_fan_watchdog_store(struct device_driver *drv, - const char *buf, size_t count) +static int fan_set_disable(void) { - unsigned long t; - - if (parse_strtoul(buf, 120, &t)) - return -EINVAL; + int rc; if (!fan_control_allowed) return -EPERM; - fan_watchdog_maxinterval = t; - fan_watchdog_reset(); - - return count; -} - -static DRIVER_ATTR(fan_watchdog, S_IWUSR | S_IRUGO, - fan_fan_watchdog_show, fan_fan_watchdog_store); - -/* --------------------------------------------------------------------- */ -static struct attribute *fan_attributes[] = { - &dev_attr_fan_pwm1_enable.attr, &dev_attr_fan_pwm1.attr, - &dev_attr_fan_fan1_input.attr, - NULL -}; - -static const struct attribute_group fan_attr_group = { - .attrs = fan_attributes, -}; - -static int __init fan_init(struct ibm_init_struct *iibm) -{ - int rc; - - vdbg_printk(TPACPI_DBG_INIT, "initializing fan subdriver\n"); - - mutex_init(&fan_mutex); - fan_status_access_mode = TPACPI_FAN_NONE; - fan_control_access_mode = TPACPI_FAN_WR_NONE; - fan_control_commands = 0; - fan_watchdog_maxinterval = 0; - tp_features.fan_ctrl_status_undef = 0; - fan_control_desired_level = 7; - - TPACPI_ACPIHANDLE_INIT(fans); - TPACPI_ACPIHANDLE_INIT(gfan); - TPACPI_ACPIHANDLE_INIT(sfan); - - if (gfan_handle) { - /* 570, 600e/x, 770e, 770x */ - fan_status_access_mode = TPACPI_FAN_RD_ACPI_GFAN; - } else { - /* all other ThinkPads: note that even old-style - * ThinkPad ECs supports the fan control register */ - if (likely(acpi_ec_read(fan_status_offset, - &fan_control_initial_status))) { - fan_status_access_mode = TPACPI_FAN_RD_TPEC; - - /* In some ThinkPads, neither the EC nor the ACPI - * DSDT initialize the fan status, and it ends up - * being set to 0x07 when it *could* be either - * 0x07 or 0x80. - * - * Enable for TP-1Y (T43), TP-78 (R51e), - * TP-76 (R52), TP-70 (T43, R52), which are known - * to be buggy. */ - if (fan_control_initial_status == 0x07) { - switch (thinkpad_id.ec_model) { - case 0x5931: /* TP-1Y */ - case 0x3837: /* TP-78 */ - case 0x3637: /* TP-76 */ - case 0x3037: /* TP-70 */ - printk(TPACPI_NOTICE - "fan_init: initial fan status " - "is unknown, assuming it is " - "in auto mode\n"); - tp_features.fan_ctrl_status_undef = 1; - ;; - } - } - } else { - printk(TPACPI_ERR - "ThinkPad ACPI EC access misbehaving, " - "fan status and control unavailable\n"); - return 1; - } - } - - if (sfan_handle) { - /* 570, 770x-JL */ - fan_control_access_mode = TPACPI_FAN_WR_ACPI_SFAN; - fan_control_commands |= - TPACPI_FAN_CMD_LEVEL | TPACPI_FAN_CMD_ENABLE; - } else { - if (!gfan_handle) { - /* gfan without sfan means no fan control */ - /* all other models implement TP EC 0x2f control */ + if (mutex_lock_interruptible(&fan_mutex)) + return -ERESTARTSYS; - if (fans_handle) { - /* X31, X40, X41 */ - fan_control_access_mode = - TPACPI_FAN_WR_ACPI_FANS; - fan_control_commands |= - TPACPI_FAN_CMD_SPEED | - TPACPI_FAN_CMD_LEVEL | - TPACPI_FAN_CMD_ENABLE; - } else { - fan_control_access_mode = TPACPI_FAN_WR_TPEC; - fan_control_commands |= - TPACPI_FAN_CMD_LEVEL | - TPACPI_FAN_CMD_ENABLE; - } + rc = 0; + switch (fan_control_access_mode) { + case TPACPI_FAN_WR_ACPI_FANS: + case TPACPI_FAN_WR_TPEC: + if (!acpi_ec_write(fan_status_offset, 0x00)) + rc = -EIO; + else { + fan_control_desired_level = 0; + tp_features.fan_ctrl_status_undef = 0; } - } - - vdbg_printk(TPACPI_DBG_INIT, "fan is %s, modes %d, %d\n", - str_supported(fan_status_access_mode != TPACPI_FAN_NONE || - fan_control_access_mode != TPACPI_FAN_WR_NONE), - fan_status_access_mode, fan_control_access_mode); - - /* fan control master switch */ - if (!fan_control_allowed) { - fan_control_access_mode = TPACPI_FAN_WR_NONE; - fan_control_commands = 0; - dbg_printk(TPACPI_DBG_INIT, - "fan control features disabled by parameter\n"); - } + break; - /* update fan_control_desired_level */ - if (fan_status_access_mode != TPACPI_FAN_NONE) - fan_get_status_safe(NULL); + case TPACPI_FAN_WR_ACPI_SFAN: + if (!acpi_evalf(sfan_handle, NULL, NULL, "vd", 0x00)) + rc = -EIO; + else + fan_control_desired_level = 0; + break; - if (fan_status_access_mode != TPACPI_FAN_NONE || - fan_control_access_mode != TPACPI_FAN_WR_NONE) { - rc = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj, - &fan_attr_group); - if (!(rc < 0)) - rc = driver_create_file(&tpacpi_hwmon_pdriver.driver, - &driver_attr_fan_watchdog); - if (rc < 0) - return rc; - return 0; - } else - return 1; + default: + rc = -ENXIO; + } + + + mutex_unlock(&fan_mutex); + return rc; } -static void fan_exit(void) +static int fan_set_speed(int speed) { - vdbg_printk(TPACPI_DBG_EXIT, - "cancelling any pending fan watchdog tasks\n"); + int rc; - /* FIXME: can we really do this unconditionally? */ - sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj, &fan_attr_group); - driver_remove_file(&tpacpi_hwmon_pdriver.driver, - &driver_attr_fan_watchdog); + if (!fan_control_allowed) + return -EPERM; - cancel_delayed_work(&fan_watchdog_task); - flush_scheduled_work(); + if (mutex_lock_interruptible(&fan_mutex)) + return -ERESTARTSYS; + + rc = 0; + switch (fan_control_access_mode) { + case TPACPI_FAN_WR_ACPI_FANS: + if (speed >= 0 && speed <= 65535) { + if (!acpi_evalf(fans_handle, NULL, NULL, "vddd", + speed, speed, speed)) + rc = -EIO; + } else + rc = -EINVAL; + break; + + default: + rc = -ENXIO; + } + + mutex_unlock(&fan_mutex); + return rc; } static int fan_read(char *p) @@ -5349,8 +4307,7 @@ static int fan_read(char *p) switch (fan_status_access_mode) { case TPACPI_FAN_RD_ACPI_GFAN: /* 570, 600e/x, 770e, 770x */ - rc = fan_get_status_safe(&status); - if (rc < 0) + if ((rc = fan_get_status_safe(&status)) < 0) return rc; len += sprintf(p + len, "status:\t\t%s\n" @@ -5360,8 +4317,7 @@ static int fan_read(char *p) case TPACPI_FAN_RD_TPEC: /* all except 570, 600e/x, 770e, 770x */ - rc = fan_get_status_safe(&status); - if (rc < 0) + if ((rc = fan_get_status_safe(&status)) < 0) return rc; if (unlikely(tp_features.fan_ctrl_status_undef)) { @@ -5376,8 +4332,7 @@ static int fan_read(char *p) len += sprintf(p + len, "status:\t\t%s\n", (status != 0) ? "enabled" : "disabled"); - rc = fan_get_speed(&speed); - if (rc < 0) + if ((rc = fan_get_speed(&speed)) < 0) return rc; len += sprintf(p + len, "speed:\t\t%d\n", speed); @@ -5413,8 +4368,8 @@ static int fan_read(char *p) if (fan_control_commands & TPACPI_FAN_CMD_ENABLE) len += sprintf(p + len, "commands:\tenable, disable\n" - "commands:\twatchdog ( " - "is 0 (off), 1-120 (seconds))\n"); + "commands:\twatchdog ( is 0 (off), " + "1-120 (seconds))\n"); if (fan_control_commands & TPACPI_FAN_CMD_SPEED) len += sprintf(p + len, "commands:\tspeed " @@ -5430,14 +4385,13 @@ static int fan_write_cmd_level(const char *cmd, int *rc) if (strlencmp(cmd, "level auto") == 0) level = TP_EC_FAN_AUTO; else if ((strlencmp(cmd, "level disengaged") == 0) | - (strlencmp(cmd, "level full-speed") == 0)) + (strlencmp(cmd, "level full-speed") == 0)) level = TP_EC_FAN_FULLSPEED; else if (sscanf(cmd, "level %d", &level) != 1) return 0; - *rc = fan_set_level_safe(level); - if (*rc == -ENXIO) - printk(TPACPI_ERR "level command accepted for unsupported " + if ((*rc = fan_set_level_safe(level)) == -ENXIO) + printk(IBM_ERR "level command accepted for unsupported " "access mode %d", fan_control_access_mode); return 1; @@ -5448,9 +4402,8 @@ static int fan_write_cmd_enable(const char *cmd, int *rc) if (strlencmp(cmd, "enable") != 0) return 0; - *rc = fan_set_enable(); - if (*rc == -ENXIO) - printk(TPACPI_ERR "enable command accepted for unsupported " + if ((*rc = fan_set_enable()) == -ENXIO) + printk(IBM_ERR "enable command accepted for unsupported " "access mode %d", fan_control_access_mode); return 1; @@ -5461,9 +4414,8 @@ static int fan_write_cmd_disable(const char *cmd, int *rc) if (strlencmp(cmd, "disable") != 0) return 0; - *rc = fan_set_disable(); - if (*rc == -ENXIO) - printk(TPACPI_ERR "disable command accepted for unsupported " + if ((*rc = fan_set_disable()) == -ENXIO) + printk(IBM_ERR "disable command accepted for unsupported " "access mode %d", fan_control_access_mode); return 1; @@ -5479,9 +4431,8 @@ static int fan_write_cmd_speed(const char *cmd, int *rc) if (sscanf(cmd, "speed %d", &speed) != 1) return 0; - *rc = fan_set_speed(speed); - if (*rc == -ENXIO) - printk(TPACPI_ERR "speed command accepted for unsupported " + if ((*rc = fan_set_speed(speed)) == -ENXIO) + printk(IBM_ERR "speed command accepted for unsupported " "access mode %d", fan_control_access_mode); return 1; @@ -5545,7 +4496,7 @@ static ssize_t thinkpad_acpi_pdev_name_show(struct device *dev, struct device_attribute *attr, char *buf) { - return snprintf(buf, PAGE_SIZE, "%s\n", TPACPI_NAME); + return snprintf(buf, PAGE_SIZE, "%s\n", IBM_NAME); } static struct device_attribute dev_attr_thinkpad_acpi_pdev_name = @@ -5556,12 +4507,14 @@ static struct device_attribute dev_attr_thinkpad_acpi_pdev_name = /* /proc support */ static struct proc_dir_entry *proc_dir; +/* Subdriver registry */ +static LIST_HEAD(tpacpi_all_drivers); + + /* * Module and infrastructure proble, init and exit handling */ -static int force_load; - #ifdef CONFIG_THINKPAD_ACPI_DEBUG static const char * __init str_supported(int is_supported) { @@ -5571,48 +4524,6 @@ static const char * __init str_supported(int is_supported) } #endif /* CONFIG_THINKPAD_ACPI_DEBUG */ -static void ibm_exit(struct ibm_struct *ibm) -{ - dbg_printk(TPACPI_DBG_EXIT, "removing %s\n", ibm->name); - - list_del_init(&ibm->all_drivers); - - if (ibm->flags.acpi_notify_installed) { - dbg_printk(TPACPI_DBG_EXIT, - "%s: acpi_remove_notify_handler\n", ibm->name); - BUG_ON(!ibm->acpi); - acpi_remove_notify_handler(*ibm->acpi->handle, - ibm->acpi->type, - dispatch_acpi_notify); - ibm->flags.acpi_notify_installed = 0; - ibm->flags.acpi_notify_installed = 0; - } - - if (ibm->flags.proc_created) { - dbg_printk(TPACPI_DBG_EXIT, - "%s: remove_proc_entry\n", ibm->name); - remove_proc_entry(ibm->name, proc_dir); - ibm->flags.proc_created = 0; - } - - if (ibm->flags.acpi_driver_registered) { - dbg_printk(TPACPI_DBG_EXIT, - "%s: acpi_bus_unregister_driver\n", ibm->name); - BUG_ON(!ibm->acpi); - acpi_bus_unregister_driver(ibm->acpi->driver); - kfree(ibm->acpi->driver); - ibm->acpi->driver = NULL; - ibm->flags.acpi_driver_registered = 0; - } - - if (ibm->flags.init_called && ibm->exit) { - ibm->exit(); - ibm->flags.init_called = 0; - } - - dbg_printk(TPACPI_DBG_INIT, "finished removing %s\n", ibm->name); -} - static int __init ibm_init(struct ibm_init_struct *iibm) { int ret; @@ -5649,7 +4560,7 @@ static int __init ibm_init(struct ibm_init_struct *iibm) if (ibm->acpi->notify) { ret = setup_acpi_notify(ibm); if (ret == -ENODEV) { - printk(TPACPI_NOTICE "disabling subdriver %s\n", + printk(IBM_NOTICE "disabling subdriver %s\n", ibm->name); ret = 0; goto err_out; @@ -5667,7 +4578,7 @@ static int __init ibm_init(struct ibm_init_struct *iibm) S_IFREG | S_IRUGO | S_IWUSR, proc_dir); if (!entry) { - printk(TPACPI_ERR "unable to create proc entry %s\n", + printk(IBM_ERR "unable to create proc entry %s\n", ibm->name); ret = -ENODEV; goto err_out; @@ -5693,6 +4604,48 @@ static int __init ibm_init(struct ibm_init_struct *iibm) return (ret < 0)? ret : 0; } +static void ibm_exit(struct ibm_struct *ibm) +{ + dbg_printk(TPACPI_DBG_EXIT, "removing %s\n", ibm->name); + + list_del_init(&ibm->all_drivers); + + if (ibm->flags.acpi_notify_installed) { + dbg_printk(TPACPI_DBG_EXIT, + "%s: acpi_remove_notify_handler\n", ibm->name); + BUG_ON(!ibm->acpi); + acpi_remove_notify_handler(*ibm->acpi->handle, + ibm->acpi->type, + dispatch_acpi_notify); + ibm->flags.acpi_notify_installed = 0; + ibm->flags.acpi_notify_installed = 0; + } + + if (ibm->flags.proc_created) { + dbg_printk(TPACPI_DBG_EXIT, + "%s: remove_proc_entry\n", ibm->name); + remove_proc_entry(ibm->name, proc_dir); + ibm->flags.proc_created = 0; + } + + if (ibm->flags.acpi_driver_registered) { + dbg_printk(TPACPI_DBG_EXIT, + "%s: acpi_bus_unregister_driver\n", ibm->name); + BUG_ON(!ibm->acpi); + acpi_bus_unregister_driver(ibm->acpi->driver); + kfree(ibm->acpi->driver); + ibm->acpi->driver = NULL; + ibm->flags.acpi_driver_registered = 0; + } + + if (ibm->flags.init_called && ibm->exit) { + ibm->exit(); + ibm->flags.init_called = 0; + } + + dbg_printk(TPACPI_DBG_INIT, "finished removing %s\n", ibm->name); +} + /* Probing */ static void __init get_thinkpad_model_data(struct thinkpad_id_data *tp) @@ -5762,10 +4715,10 @@ static int __init probe_for_thinkpad(void) is_thinkpad = (thinkpad_id.model_str != NULL); /* ec is required because many other handles are relative to it */ - TPACPI_ACPIHANDLE_INIT(ec); + IBM_ACPIHANDLE_INIT(ec); if (!ec_handle) { if (is_thinkpad) - printk(TPACPI_ERR + printk(IBM_ERR "Not yet supported ThinkPad detected!\n"); return -ENODEV; } @@ -5886,110 +4839,47 @@ static int __init set_ibm_param(const char *val, struct kernel_param *kp) return -EINVAL; } +static int experimental; module_param(experimental, int, 0); -MODULE_PARM_DESC(experimental, - "Enables experimental features when non-zero"); +static u32 dbg_level; module_param_named(debug, dbg_level, uint, 0); -MODULE_PARM_DESC(debug, "Sets debug level bit-mask"); +static int force_load; module_param(force_load, bool, 0); -MODULE_PARM_DESC(force_load, - "Attempts to load the driver even on a " - "mis-identified ThinkPad when true"); +static int fan_control_allowed; module_param_named(fan_control, fan_control_allowed, bool, 0); -MODULE_PARM_DESC(fan_control, - "Enables setting fan parameters features when true"); +static int brightness_mode; module_param_named(brightness_mode, brightness_mode, int, 0); -MODULE_PARM_DESC(brightness_mode, - "Selects brightness control strategy: " - "0=auto, 1=EC, 2=CMOS, 3=both"); +static unsigned int brightness_enable = 2; /* 2 = auto, 0 = no, 1 = yes */ module_param(brightness_enable, uint, 0); -MODULE_PARM_DESC(brightness_enable, - "Enables backlight control when 1, disables when 0"); +static unsigned int hotkey_report_mode; module_param(hotkey_report_mode, uint, 0); -MODULE_PARM_DESC(hotkey_report_mode, - "used for backwards compatibility with userspace, " - "see documentation"); - -#define TPACPI_PARAM(feature) \ - module_param_call(feature, set_ibm_param, NULL, NULL, 0); \ - MODULE_PARM_DESC(feature, "Simulates thinkpad-aci procfs command " \ - "at module load, see documentation") - -TPACPI_PARAM(hotkey); -TPACPI_PARAM(bluetooth); -TPACPI_PARAM(video); -TPACPI_PARAM(light); + +#define IBM_PARAM(feature) \ + module_param_call(feature, set_ibm_param, NULL, NULL, 0) + +IBM_PARAM(hotkey); +IBM_PARAM(bluetooth); +IBM_PARAM(video); +IBM_PARAM(light); #ifdef CONFIG_THINKPAD_ACPI_DOCK -TPACPI_PARAM(dock); +IBM_PARAM(dock); #endif #ifdef CONFIG_THINKPAD_ACPI_BAY -TPACPI_PARAM(bay); +IBM_PARAM(bay); #endif /* CONFIG_THINKPAD_ACPI_BAY */ -TPACPI_PARAM(cmos); -TPACPI_PARAM(led); -TPACPI_PARAM(beep); -TPACPI_PARAM(ecdump); -TPACPI_PARAM(brightness); -TPACPI_PARAM(volume); -TPACPI_PARAM(fan); - -static void thinkpad_acpi_module_exit(void) -{ - struct ibm_struct *ibm, *itmp; - - tpacpi_lifecycle = TPACPI_LIFE_EXITING; - - list_for_each_entry_safe_reverse(ibm, itmp, - &tpacpi_all_drivers, - all_drivers) { - ibm_exit(ibm); - } - - dbg_printk(TPACPI_DBG_INIT, "finished subdriver exit path...\n"); - - if (tpacpi_inputdev) { - if (tp_features.input_device_registered) - input_unregister_device(tpacpi_inputdev); - else - input_free_device(tpacpi_inputdev); - } - - if (tpacpi_hwmon) - hwmon_device_unregister(tpacpi_hwmon); - - if (tp_features.sensors_pdev_attrs_registered) - device_remove_file(&tpacpi_sensors_pdev->dev, - &dev_attr_thinkpad_acpi_pdev_name); - if (tpacpi_sensors_pdev) - platform_device_unregister(tpacpi_sensors_pdev); - if (tpacpi_pdev) - platform_device_unregister(tpacpi_pdev); - - if (tp_features.sensors_pdrv_attrs_registered) - tpacpi_remove_driver_attributes(&tpacpi_hwmon_pdriver.driver); - if (tp_features.platform_drv_attrs_registered) - tpacpi_remove_driver_attributes(&tpacpi_pdriver.driver); - - if (tp_features.sensors_pdrv_registered) - platform_driver_unregister(&tpacpi_hwmon_pdriver); - - if (tp_features.platform_drv_registered) - platform_driver_unregister(&tpacpi_pdriver); - - if (proc_dir) - remove_proc_entry(TPACPI_PROC_DIR, acpi_root_dir); - - kfree(thinkpad_id.bios_version_str); - kfree(thinkpad_id.ec_version_str); - kfree(thinkpad_id.model_str); -} - +IBM_PARAM(cmos); +IBM_PARAM(led); +IBM_PARAM(beep); +IBM_PARAM(ecdump); +IBM_PARAM(brightness); +IBM_PARAM(volume); +IBM_PARAM(fan); static int __init thinkpad_acpi_module_init(void) { @@ -6012,13 +4902,12 @@ static int __init thinkpad_acpi_module_init(void) /* Driver initialization */ - TPACPI_ACPIHANDLE_INIT(ecrd); - TPACPI_ACPIHANDLE_INIT(ecwr); + IBM_ACPIHANDLE_INIT(ecrd); + IBM_ACPIHANDLE_INIT(ecwr); - proc_dir = proc_mkdir(TPACPI_PROC_DIR, acpi_root_dir); + proc_dir = proc_mkdir(IBM_PROC_DIR, acpi_root_dir); if (!proc_dir) { - printk(TPACPI_ERR - "unable to create proc dir " TPACPI_PROC_DIR); + printk(IBM_ERR "unable to create proc dir " IBM_PROC_DIR); thinkpad_acpi_module_exit(); return -ENODEV; } @@ -6026,8 +4915,7 @@ static int __init thinkpad_acpi_module_init(void) ret = platform_driver_register(&tpacpi_pdriver); if (ret) { - printk(TPACPI_ERR - "unable to register main platform driver\n"); + printk(IBM_ERR "unable to register main platform driver\n"); thinkpad_acpi_module_exit(); return ret; } @@ -6035,8 +4923,7 @@ static int __init thinkpad_acpi_module_init(void) ret = platform_driver_register(&tpacpi_hwmon_pdriver); if (ret) { - printk(TPACPI_ERR - "unable to register hwmon platform driver\n"); + printk(IBM_ERR "unable to register hwmon platform driver\n"); thinkpad_acpi_module_exit(); return ret; } @@ -6045,12 +4932,10 @@ static int __init thinkpad_acpi_module_init(void) ret = tpacpi_create_driver_attributes(&tpacpi_pdriver.driver); if (!ret) { tp_features.platform_drv_attrs_registered = 1; - ret = tpacpi_create_driver_attributes( - &tpacpi_hwmon_pdriver.driver); + ret = tpacpi_create_driver_attributes(&tpacpi_hwmon_pdriver.driver); } if (ret) { - printk(TPACPI_ERR - "unable to create sysfs driver attributes\n"); + printk(IBM_ERR "unable to create sysfs driver attributes\n"); thinkpad_acpi_module_exit(); return ret; } @@ -6058,31 +4943,30 @@ static int __init thinkpad_acpi_module_init(void) /* Device initialization */ - tpacpi_pdev = platform_device_register_simple(TPACPI_DRVR_NAME, -1, + tpacpi_pdev = platform_device_register_simple(IBM_DRVR_NAME, -1, NULL, 0); if (IS_ERR(tpacpi_pdev)) { ret = PTR_ERR(tpacpi_pdev); tpacpi_pdev = NULL; - printk(TPACPI_ERR "unable to register platform device\n"); + printk(IBM_ERR "unable to register platform device\n"); thinkpad_acpi_module_exit(); return ret; } tpacpi_sensors_pdev = platform_device_register_simple( - TPACPI_HWMON_DRVR_NAME, - -1, NULL, 0); + IBM_HWMON_DRVR_NAME, + -1, NULL, 0); if (IS_ERR(tpacpi_sensors_pdev)) { ret = PTR_ERR(tpacpi_sensors_pdev); tpacpi_sensors_pdev = NULL; - printk(TPACPI_ERR - "unable to register hwmon platform device\n"); + printk(IBM_ERR "unable to register hwmon platform device\n"); thinkpad_acpi_module_exit(); return ret; } ret = device_create_file(&tpacpi_sensors_pdev->dev, &dev_attr_thinkpad_acpi_pdev_name); if (ret) { - printk(TPACPI_ERR - "unable to create sysfs hwmon device attributes\n"); + printk(IBM_ERR + "unable to create sysfs hwmon device attributes\n"); thinkpad_acpi_module_exit(); return ret; } @@ -6091,20 +4975,20 @@ static int __init thinkpad_acpi_module_init(void) if (IS_ERR(tpacpi_hwmon)) { ret = PTR_ERR(tpacpi_hwmon); tpacpi_hwmon = NULL; - printk(TPACPI_ERR "unable to register hwmon device\n"); + printk(IBM_ERR "unable to register hwmon device\n"); thinkpad_acpi_module_exit(); return ret; } mutex_init(&tpacpi_inputdev_send_mutex); tpacpi_inputdev = input_allocate_device(); if (!tpacpi_inputdev) { - printk(TPACPI_ERR "unable to allocate input device\n"); + printk(IBM_ERR "unable to allocate input device\n"); thinkpad_acpi_module_exit(); return -ENOMEM; } else { /* Prepare input device, but don't register */ tpacpi_inputdev->name = "ThinkPad Extra Buttons"; - tpacpi_inputdev->phys = TPACPI_DRVR_NAME "/input0"; + tpacpi_inputdev->phys = IBM_DRVR_NAME "/input0"; tpacpi_inputdev->id.bustype = BUS_HOST; tpacpi_inputdev->id.vendor = (thinkpad_id.vendor) ? thinkpad_id.vendor : @@ -6123,7 +5007,7 @@ static int __init thinkpad_acpi_module_init(void) } ret = input_register_device(tpacpi_inputdev); if (ret < 0) { - printk(TPACPI_ERR "unable to register input device\n"); + printk(IBM_ERR "unable to register input device\n"); thinkpad_acpi_module_exit(); return ret; } else { @@ -6134,36 +5018,56 @@ static int __init thinkpad_acpi_module_init(void) return 0; } -/* Please remove this in year 2009 */ -MODULE_ALIAS("ibm_acpi"); +static void thinkpad_acpi_module_exit(void) +{ + struct ibm_struct *ibm, *itmp; -/* - * DMI matching for module autoloading - * - * See http://thinkwiki.org/wiki/List_of_DMI_IDs - * See http://thinkwiki.org/wiki/BIOS_Upgrade_Downloads - * - * Only models listed in thinkwiki will be supported, so add yours - * if it is not there yet. - */ -#define IBM_BIOS_MODULE_ALIAS(__type) \ - MODULE_ALIAS("dmi:bvnIBM:bvr" __type "ET??WW") + tpacpi_lifecycle = TPACPI_LIFE_EXITING; -/* Non-ancient thinkpads */ -MODULE_ALIAS("dmi:bvnIBM:*:svnIBM:*:pvrThinkPad*:rvnIBM:*"); -MODULE_ALIAS("dmi:bvnLENOVO:*:svnLENOVO:*:pvrThinkPad*:rvnLENOVO:*"); + list_for_each_entry_safe_reverse(ibm, itmp, + &tpacpi_all_drivers, + all_drivers) { + ibm_exit(ibm); + } -/* Ancient thinkpad BIOSes have to be identified by - * BIOS type or model number, and there are far less - * BIOS types than model numbers... */ -IBM_BIOS_MODULE_ALIAS("I[B,D,H,I,M,N,O,T,W,V,Y,Z]"); -IBM_BIOS_MODULE_ALIAS("1[0,3,6,8,A-G,I,K,M-P,S,T]"); -IBM_BIOS_MODULE_ALIAS("K[U,X-Z]"); + dbg_printk(TPACPI_DBG_INIT, "finished subdriver exit path...\n"); -MODULE_AUTHOR("Borislav Deianov, Henrique de Moraes Holschuh"); -MODULE_DESCRIPTION(TPACPI_DESC); -MODULE_VERSION(TPACPI_VERSION); -MODULE_LICENSE("GPL"); + if (tpacpi_inputdev) { + if (tp_features.input_device_registered) + input_unregister_device(tpacpi_inputdev); + else + input_free_device(tpacpi_inputdev); + } + + if (tpacpi_hwmon) + hwmon_device_unregister(tpacpi_hwmon); + + if (tp_features.sensors_pdev_attrs_registered) + device_remove_file(&tpacpi_sensors_pdev->dev, + &dev_attr_thinkpad_acpi_pdev_name); + if (tpacpi_sensors_pdev) + platform_device_unregister(tpacpi_sensors_pdev); + if (tpacpi_pdev) + platform_device_unregister(tpacpi_pdev); + + if (tp_features.sensors_pdrv_attrs_registered) + tpacpi_remove_driver_attributes(&tpacpi_hwmon_pdriver.driver); + if (tp_features.platform_drv_attrs_registered) + tpacpi_remove_driver_attributes(&tpacpi_pdriver.driver); + + if (tp_features.sensors_pdrv_registered) + platform_driver_unregister(&tpacpi_hwmon_pdriver); + + if (tp_features.platform_drv_registered) + platform_driver_unregister(&tpacpi_pdriver); + + if (proc_dir) + remove_proc_entry(IBM_PROC_DIR, acpi_root_dir); + + kfree(thinkpad_id.bios_version_str); + kfree(thinkpad_id.ec_version_str); + kfree(thinkpad_id.model_str); +} module_init(thinkpad_acpi_module_init); module_exit(thinkpad_acpi_module_exit); diff --git a/trunk/drivers/misc/thinkpad_acpi.h b/trunk/drivers/misc/thinkpad_acpi.h new file mode 100644 index 000000000000..8fba2bbe345e --- /dev/null +++ b/trunk/drivers/misc/thinkpad_acpi.h @@ -0,0 +1,606 @@ +/* + * thinkpad_acpi.h - ThinkPad ACPI Extras + * + * + * Copyright (C) 2004-2005 Borislav Deianov + * Copyright (C) 2006-2007 Henrique de Moraes Holschuh + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef __THINKPAD_ACPI_H__ +#define __THINKPAD_ACPI_H__ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +/**************************************************************************** + * Main driver + */ + +#define IBM_NAME "thinkpad" +#define IBM_DESC "ThinkPad ACPI Extras" +#define IBM_FILE IBM_NAME "_acpi" +#define IBM_URL "http://ibm-acpi.sf.net/" +#define IBM_MAIL "ibm-acpi-devel@lists.sourceforge.net" + +#define IBM_PROC_DIR "ibm" +#define IBM_ACPI_EVENT_PREFIX "ibm" +#define IBM_DRVR_NAME IBM_FILE +#define IBM_HWMON_DRVR_NAME IBM_NAME "_hwmon" + +#define IBM_LOG IBM_FILE ": " +#define IBM_ERR KERN_ERR IBM_LOG +#define IBM_NOTICE KERN_NOTICE IBM_LOG +#define IBM_INFO KERN_INFO IBM_LOG +#define IBM_DEBUG KERN_DEBUG IBM_LOG + +#define IBM_MAX_ACPI_ARGS 3 + +/* ThinkPad CMOS commands */ +#define TP_CMOS_VOLUME_DOWN 0 +#define TP_CMOS_VOLUME_UP 1 +#define TP_CMOS_VOLUME_MUTE 2 +#define TP_CMOS_BRIGHTNESS_UP 4 +#define TP_CMOS_BRIGHTNESS_DOWN 5 + +/* ThinkPad CMOS NVRAM constants */ +#define TP_NVRAM_ADDR_BRIGHTNESS 0x5e +#define TP_NVRAM_MASK_LEVEL_BRIGHTNESS 0x0f +#define TP_NVRAM_POS_LEVEL_BRIGHTNESS 0 + +#define onoff(status,bit) ((status) & (1 << (bit)) ? "on" : "off") +#define enabled(status,bit) ((status) & (1 << (bit)) ? "enabled" : "disabled") +#define strlencmp(a,b) (strncmp((a), (b), strlen(b))) + +/* Debugging */ +#define TPACPI_DBG_ALL 0xffff +#define TPACPI_DBG_ALL 0xffff +#define TPACPI_DBG_INIT 0x0001 +#define TPACPI_DBG_EXIT 0x0002 +#define dbg_printk(a_dbg_level, format, arg...) \ + do { if (dbg_level & a_dbg_level) \ + printk(IBM_DEBUG "%s: " format, __func__ , ## arg); } while (0) +#ifdef CONFIG_THINKPAD_ACPI_DEBUG +#define vdbg_printk(a_dbg_level, format, arg...) \ + dbg_printk(a_dbg_level, format, ## arg) +static const char *str_supported(int is_supported); +#else +#define vdbg_printk(a_dbg_level, format, arg...) +#endif + +/* Input IDs */ +#define TPACPI_HKEY_INPUT_VENDOR PCI_VENDOR_ID_IBM +#define TPACPI_HKEY_INPUT_PRODUCT 0x5054 /* "TP" */ +#define TPACPI_HKEY_INPUT_VERSION 0x4101 + +/* ACPI HIDs */ +#define IBM_HKEY_HID "IBM0068" + +/* ACPI helpers */ +static int __must_check acpi_evalf(acpi_handle handle, + void *res, char *method, char *fmt, ...); +static int __must_check acpi_ec_read(int i, u8 * p); +static int __must_check acpi_ec_write(int i, u8 v); +static int __must_check _sta(acpi_handle handle); + +/* ACPI handles */ +static acpi_handle root_handle; /* root namespace */ +static acpi_handle ec_handle; /* EC */ +static acpi_handle ecrd_handle, ecwr_handle; /* 570 EC access */ +static acpi_handle cmos_handle, hkey_handle; /* basic thinkpad handles */ + +static void drv_acpi_handle_init(char *name, + acpi_handle *handle, acpi_handle parent, + char **paths, int num_paths, char **path); +#define IBM_ACPIHANDLE_INIT(object) \ + drv_acpi_handle_init(#object, &object##_handle, *object##_parent, \ + object##_paths, ARRAY_SIZE(object##_paths), &object##_path) + +/* ThinkPad ACPI helpers */ +static int issue_thinkpad_cmos_command(int cmos_cmd); + +/* procfs support */ +static struct proc_dir_entry *proc_dir; + +/* procfs helpers */ +static int dispatch_procfs_read(char *page, char **start, off_t off, + int count, int *eof, void *data); +static int dispatch_procfs_write(struct file *file, + const char __user * userbuf, + unsigned long count, void *data); +static char *next_cmd(char **cmds); + +/* sysfs support */ +struct attribute_set { + unsigned int members, max_members; + struct attribute_group group; +}; + +static struct attribute_set *create_attr_set(unsigned int max_members, + const char* name); +#define destroy_attr_set(_set) \ + kfree(_set); +static int add_to_attr_set(struct attribute_set* s, struct attribute *attr); +static int add_many_to_attr_set(struct attribute_set* s, + struct attribute **attr, + unsigned int count); +#define register_attr_set_with_sysfs(_attr_set, _kobj) \ + sysfs_create_group(_kobj, &_attr_set->group) +static void delete_attr_set(struct attribute_set* s, struct kobject *kobj); + +static int parse_strtoul(const char *buf, unsigned long max, + unsigned long *value); + +/* Device model */ +static struct platform_device *tpacpi_pdev; +static struct platform_device *tpacpi_sensors_pdev; +static struct device *tpacpi_hwmon; +static struct platform_driver tpacpi_pdriver; +static struct input_dev *tpacpi_inputdev; +static int tpacpi_create_driver_attributes(struct device_driver *drv); +static void tpacpi_remove_driver_attributes(struct device_driver *drv); + +/* Module */ +static int experimental; +static u32 dbg_level; +static int force_load; +static unsigned int hotkey_report_mode; + +static int thinkpad_acpi_module_init(void); +static void thinkpad_acpi_module_exit(void); + + +/**************************************************************************** + * Subdrivers + */ + +struct ibm_struct; + +struct tp_acpi_drv_struct { + const struct acpi_device_id *hid; + struct acpi_driver *driver; + + void (*notify) (struct ibm_struct *, u32); + acpi_handle *handle; + u32 type; + struct acpi_device *device; +}; + +struct ibm_struct { + char *name; + + int (*read) (char *); + int (*write) (char *); + void (*exit) (void); + void (*resume) (void); + + struct list_head all_drivers; + + struct tp_acpi_drv_struct *acpi; + + struct { + u8 acpi_driver_registered:1; + u8 acpi_notify_installed:1; + u8 proc_created:1; + u8 init_called:1; + u8 experimental:1; + } flags; +}; + +struct ibm_init_struct { + char param[32]; + + int (*init) (struct ibm_init_struct *); + struct ibm_struct *data; +}; + +static struct { +#ifdef CONFIG_THINKPAD_ACPI_BAY + u32 bay_status:1; + u32 bay_eject:1; + u32 bay_status2:1; + u32 bay_eject2:1; +#endif + u32 bluetooth:1; + u32 hotkey:1; + u32 hotkey_mask:1; + u32 hotkey_wlsw:1; + u32 light:1; + u32 light_status:1; + u32 bright_16levels:1; + u32 wan:1; + u32 fan_ctrl_status_undef:1; + u32 input_device_registered:1; + u32 platform_drv_registered:1; + u32 platform_drv_attrs_registered:1; + u32 sensors_pdrv_registered:1; + u32 sensors_pdrv_attrs_registered:1; + u32 sensors_pdev_attrs_registered:1; +} tp_features; + +struct thinkpad_id_data { + unsigned int vendor; /* ThinkPad vendor: + * PCI_VENDOR_ID_IBM/PCI_VENDOR_ID_LENOVO */ + + char *bios_version_str; /* Something like 1ZET51WW (1.03z) */ + char *ec_version_str; /* Something like 1ZHT51WW-1.04a */ + + u16 bios_model; /* Big Endian, TP-1Y = 0x5931, 0 = unknown */ + u16 ec_model; + + char *model_str; +}; + +static struct thinkpad_id_data thinkpad_id; + +static struct list_head tpacpi_all_drivers; + +static struct ibm_init_struct ibms_init[]; +static int set_ibm_param(const char *val, struct kernel_param *kp); +static int ibm_init(struct ibm_init_struct *iibm); +static void ibm_exit(struct ibm_struct *ibm); + + +/* + * procfs master subdriver + */ +static int thinkpad_acpi_driver_init(struct ibm_init_struct *iibm); +static int thinkpad_acpi_driver_read(char *p); + + +/* + * Bay subdriver + */ + +#ifdef CONFIG_THINKPAD_ACPI_BAY +static acpi_handle bay_handle, bay_ej_handle; +static acpi_handle bay2_handle, bay2_ej_handle; + +static int bay_init(struct ibm_init_struct *iibm); +static void bay_notify(struct ibm_struct *ibm, u32 event); +static int bay_read(char *p); +static int bay_write(char *buf); +#endif /* CONFIG_THINKPAD_ACPI_BAY */ + + +/* + * Beep subdriver + */ + +static acpi_handle beep_handle; + +static int beep_read(char *p); +static int beep_write(char *buf); + + +/* + * Bluetooth subdriver + */ + +enum { + /* ACPI GBDC/SBDC bits */ + TP_ACPI_BLUETOOTH_HWPRESENT = 0x01, /* Bluetooth hw available */ + TP_ACPI_BLUETOOTH_RADIOSSW = 0x02, /* Bluetooth radio enabled */ + TP_ACPI_BLUETOOTH_UNK = 0x04, /* unknown function */ +}; + +static int bluetooth_init(struct ibm_init_struct *iibm); +static int bluetooth_get_radiosw(void); +static int bluetooth_set_radiosw(int radio_on); +static int bluetooth_read(char *p); +static int bluetooth_write(char *buf); + + +/* + * Brightness (backlight) subdriver + */ + +#define TPACPI_BACKLIGHT_DEV_NAME "thinkpad_screen" + +static struct backlight_device *ibm_backlight_device; +static int brightness_offset = 0x31; +static int brightness_mode; +static unsigned int brightness_enable; /* 0 = no, 1 = yes, 2 = auto */ + +static int brightness_init(struct ibm_init_struct *iibm); +static void brightness_exit(void); +static int brightness_get(struct backlight_device *bd); +static int brightness_set(int value); +static int brightness_update_status(struct backlight_device *bd); +static int brightness_read(char *p); +static int brightness_write(char *buf); + + +/* + * CMOS subdriver + */ + +static int cmos_read(char *p); +static int cmos_write(char *buf); + + +/* + * Dock subdriver + */ + +#ifdef CONFIG_THINKPAD_ACPI_DOCK +static acpi_handle pci_handle; +static acpi_handle dock_handle; + +static void dock_notify(struct ibm_struct *ibm, u32 event); +static int dock_read(char *p); +static int dock_write(char *buf); +#endif /* CONFIG_THINKPAD_ACPI_DOCK */ + + +/* + * EC dump subdriver + */ + +static int ecdump_read(char *p) ; +static int ecdump_write(char *buf); + + +/* + * Fan subdriver + */ + +enum { /* Fan control constants */ + fan_status_offset = 0x2f, /* EC register 0x2f */ + fan_rpm_offset = 0x84, /* EC register 0x84: LSB, 0x85 MSB (RPM) + * 0x84 must be read before 0x85 */ + + TP_EC_FAN_FULLSPEED = 0x40, /* EC fan mode: full speed */ + TP_EC_FAN_AUTO = 0x80, /* EC fan mode: auto fan control */ + + TPACPI_FAN_LAST_LEVEL = 0x100, /* Use cached last-seen fan level */ +}; + +enum fan_status_access_mode { + TPACPI_FAN_NONE = 0, /* No fan status or control */ + TPACPI_FAN_RD_ACPI_GFAN, /* Use ACPI GFAN */ + TPACPI_FAN_RD_TPEC, /* Use ACPI EC regs 0x2f, 0x84-0x85 */ +}; + +enum fan_control_access_mode { + TPACPI_FAN_WR_NONE = 0, /* No fan control */ + TPACPI_FAN_WR_ACPI_SFAN, /* Use ACPI SFAN */ + TPACPI_FAN_WR_TPEC, /* Use ACPI EC reg 0x2f */ + TPACPI_FAN_WR_ACPI_FANS, /* Use ACPI FANS and EC reg 0x2f */ +}; + +enum fan_control_commands { + TPACPI_FAN_CMD_SPEED = 0x0001, /* speed command */ + TPACPI_FAN_CMD_LEVEL = 0x0002, /* level command */ + TPACPI_FAN_CMD_ENABLE = 0x0004, /* enable/disable cmd, + * and also watchdog cmd */ +}; + +static int fan_control_allowed; + +static enum fan_status_access_mode fan_status_access_mode; +static enum fan_control_access_mode fan_control_access_mode; +static enum fan_control_commands fan_control_commands; +static u8 fan_control_initial_status; +static u8 fan_control_desired_level; +static int fan_watchdog_maxinterval; + +static struct mutex fan_mutex; + +static acpi_handle fans_handle, gfan_handle, sfan_handle; + +static int fan_init(struct ibm_init_struct *iibm); +static void fan_exit(void); +static int fan_get_status(u8 *status); +static int fan_get_status_safe(u8 *status); +static int fan_get_speed(unsigned int *speed); +static void fan_update_desired_level(u8 status); +static void fan_watchdog_fire(struct work_struct *ignored); +static void fan_watchdog_reset(void); +static int fan_set_level(int level); +static int fan_set_level_safe(int level); +static int fan_set_enable(void); +static int fan_set_disable(void); +static int fan_set_speed(int speed); +static int fan_read(char *p); +static int fan_write(char *buf); +static int fan_write_cmd_level(const char *cmd, int *rc); +static int fan_write_cmd_enable(const char *cmd, int *rc); +static int fan_write_cmd_disable(const char *cmd, int *rc); +static int fan_write_cmd_speed(const char *cmd, int *rc); +static int fan_write_cmd_watchdog(const char *cmd, int *rc); + + +/* + * Hotkey subdriver + */ + +static int hotkey_orig_status; +static u32 hotkey_orig_mask; + +static struct mutex hotkey_mutex; + +static int hotkey_init(struct ibm_init_struct *iibm); +static void hotkey_exit(void); +static int hotkey_get(int *status, u32 *mask); +static int hotkey_set(int status, u32 mask); +static void hotkey_notify(struct ibm_struct *ibm, u32 event); +static int hotkey_read(char *p); +static int hotkey_write(char *buf); + + +/* + * LED subdriver + */ + +enum led_access_mode { + TPACPI_LED_NONE = 0, + TPACPI_LED_570, /* 570 */ + TPACPI_LED_OLD, /* 600e/x, 770e, 770x, A21e, A2xm/p, T20-22, X20-21 */ + TPACPI_LED_NEW, /* all others */ +}; + +enum { /* For TPACPI_LED_OLD */ + TPACPI_LED_EC_HLCL = 0x0c, /* EC reg to get led to power on */ + TPACPI_LED_EC_HLBL = 0x0d, /* EC reg to blink a lit led */ + TPACPI_LED_EC_HLMS = 0x0e, /* EC reg to select led to command */ +}; + +static enum led_access_mode led_supported; +static acpi_handle led_handle; + +static int led_init(struct ibm_init_struct *iibm); +static int led_read(char *p); +static int led_write(char *buf); + +/* + * Light (thinklight) subdriver + */ + +static acpi_handle lght_handle, ledb_handle; + +static int light_init(struct ibm_init_struct *iibm); +static int light_read(char *p); +static int light_write(char *buf); + + +/* + * Thermal subdriver + */ + +enum thermal_access_mode { + TPACPI_THERMAL_NONE = 0, /* No thermal support */ + TPACPI_THERMAL_ACPI_TMP07, /* Use ACPI TMP0-7 */ + TPACPI_THERMAL_ACPI_UPDT, /* Use ACPI TMP0-7 with UPDT */ + TPACPI_THERMAL_TPEC_8, /* Use ACPI EC regs, 8 sensors */ + TPACPI_THERMAL_TPEC_16, /* Use ACPI EC regs, 16 sensors */ +}; + +enum { /* TPACPI_THERMAL_TPEC_* */ + TP_EC_THERMAL_TMP0 = 0x78, /* ACPI EC regs TMP 0..7 */ + TP_EC_THERMAL_TMP8 = 0xC0, /* ACPI EC regs TMP 8..15 */ + TP_EC_THERMAL_TMP_NA = -128, /* ACPI EC sensor not available */ +}; + +#define TPACPI_MAX_THERMAL_SENSORS 16 /* Max thermal sensors supported */ +struct ibm_thermal_sensors_struct { + s32 temp[TPACPI_MAX_THERMAL_SENSORS]; +}; + +static enum thermal_access_mode thermal_read_mode; + +static int thermal_init(struct ibm_init_struct *iibm); +static int thermal_get_sensor(int idx, s32 *value); +static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s); +static int thermal_read(char *p); + + +/* + * Video subdriver + */ + +enum video_access_mode { + TPACPI_VIDEO_NONE = 0, + TPACPI_VIDEO_570, /* 570 */ + TPACPI_VIDEO_770, /* 600e/x, 770e, 770x */ + TPACPI_VIDEO_NEW, /* all others */ +}; + +enum { /* video status flags, based on VIDEO_570 */ + TP_ACPI_VIDEO_S_LCD = 0x01, /* LCD output enabled */ + TP_ACPI_VIDEO_S_CRT = 0x02, /* CRT output enabled */ + TP_ACPI_VIDEO_S_DVI = 0x08, /* DVI output enabled */ +}; + +enum { /* TPACPI_VIDEO_570 constants */ + TP_ACPI_VIDEO_570_PHSCMD = 0x87, /* unknown magic constant :( */ + TP_ACPI_VIDEO_570_PHSMASK = 0x03, /* PHS bits that map to + * video_status_flags */ + TP_ACPI_VIDEO_570_PHS2CMD = 0x8b, /* unknown magic constant :( */ + TP_ACPI_VIDEO_570_PHS2SET = 0x80, /* unknown magic constant :( */ +}; + +static enum video_access_mode video_supported; +static int video_orig_autosw; +static acpi_handle vid_handle, vid2_handle; + +static int video_init(struct ibm_init_struct *iibm); +static void video_exit(void); +static int video_outputsw_get(void); +static int video_outputsw_set(int status); +static int video_autosw_get(void); +static int video_autosw_set(int enable); +static int video_outputsw_cycle(void); +static int video_expand_toggle(void); +static int video_read(char *p); +static int video_write(char *buf); + + +/* + * Volume subdriver + */ + +static int volume_offset = 0x30; + +static int volume_read(char *p); +static int volume_write(char *buf); + + +/* + * Wan subdriver + */ + +enum { + /* ACPI GWAN/SWAN bits */ + TP_ACPI_WANCARD_HWPRESENT = 0x01, /* Wan hw available */ + TP_ACPI_WANCARD_RADIOSSW = 0x02, /* Wan radio enabled */ + TP_ACPI_WANCARD_UNK = 0x04, /* unknown function */ +}; + +static int wan_init(struct ibm_init_struct *iibm); +static int wan_get_radiosw(void); +static int wan_set_radiosw(int radio_on); +static int wan_read(char *p); +static int wan_write(char *buf); + + +#endif /* __THINKPAD_ACPI_H */ diff --git a/trunk/drivers/pnp/pnpacpi/core.c b/trunk/drivers/pnp/pnpacpi/core.c index 662b4c279cfc..dada89906314 100644 --- a/trunk/drivers/pnp/pnpacpi/core.c +++ b/trunk/drivers/pnp/pnpacpi/core.c @@ -183,7 +183,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device) if (ACPI_SUCCESS(status)) dev->capabilities |= PNP_CONFIGURABLE; dev->capabilities |= PNP_READ; - if (device->flags.dynamic_status && (dev->capabilities & PNP_CONFIGURABLE)) + if (device->flags.dynamic_status) dev->capabilities |= PNP_WRITE; if (device->flags.removable) dev->capabilities |= PNP_REMOVABLE; diff --git a/trunk/drivers/power/power_supply_sysfs.c b/trunk/drivers/power/power_supply_sysfs.c index ad2bed0174d6..d4824840c5bf 100644 --- a/trunk/drivers/power/power_supply_sysfs.c +++ b/trunk/drivers/power/power_supply_sysfs.c @@ -116,7 +116,6 @@ static struct device_attribute power_supply_attrs[] = { /* Properties of type `const char *' */ POWER_SUPPLY_ATTR(model_name), POWER_SUPPLY_ATTR(manufacturer), - POWER_SUPPLY_ATTR(serial_number), }; static ssize_t power_supply_show_static_attrs(struct device *dev, diff --git a/trunk/drivers/thermal/Kconfig b/trunk/drivers/thermal/Kconfig deleted file mode 100644 index 9b3f61200000..000000000000 --- a/trunk/drivers/thermal/Kconfig +++ /dev/null @@ -1,15 +0,0 @@ -# -# Generic thermal sysfs drivers configuration -# - -menuconfig THERMAL - bool "Generic Thermal sysfs driver" - default y - help - Generic Thermal Sysfs driver offers a generic mechanism for - thermal management. Usually it's made up of one or more thermal - zone and cooling device. - each thermal zone contains its own temperature, trip points, - cooling devices. - All platforms with ACPI thermal support can use this driver. - If you want this support, you should say Y here diff --git a/trunk/drivers/thermal/Makefile b/trunk/drivers/thermal/Makefile deleted file mode 100644 index 8ef1232de376..000000000000 --- a/trunk/drivers/thermal/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for sensor chip drivers. -# - -obj-$(CONFIG_THERMAL) += thermal.o diff --git a/trunk/drivers/thermal/thermal.c b/trunk/drivers/thermal/thermal.c deleted file mode 100644 index 3273e348fd14..000000000000 --- a/trunk/drivers/thermal/thermal.c +++ /dev/null @@ -1,714 +0,0 @@ -/* - * thermal.c - Generic Thermal Management Sysfs support. - * - * Copyright (C) 2008 Intel Corp - * Copyright (C) 2008 Zhang Rui - * Copyright (C) 2008 Sujith Thomas - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Zhang Rui") -MODULE_DESCRIPTION("Generic thermal management sysfs support"); -MODULE_LICENSE("GPL"); - -#define PREFIX "Thermal: " - -struct thermal_cooling_device_instance { - int id; - char name[THERMAL_NAME_LENGTH]; - struct thermal_zone_device *tz; - struct thermal_cooling_device *cdev; - int trip; - char attr_name[THERMAL_NAME_LENGTH]; - struct device_attribute attr; - struct list_head node; -}; - -static DEFINE_IDR(thermal_tz_idr); -static DEFINE_IDR(thermal_cdev_idr); -static DEFINE_MUTEX(thermal_idr_lock); - -static LIST_HEAD(thermal_tz_list); -static LIST_HEAD(thermal_cdev_list); -static DEFINE_MUTEX(thermal_list_lock); - -static int get_idr(struct idr *idr, struct mutex *lock, int *id) -{ - int err; - - again: - if (unlikely(idr_pre_get(idr, GFP_KERNEL) == 0)) - return -ENOMEM; - - if (lock) - mutex_lock(lock); - err = idr_get_new(idr, NULL, id); - if (lock) - mutex_unlock(lock); - if (unlikely(err == -EAGAIN)) - goto again; - else if (unlikely(err)) - return err; - - *id = *id & MAX_ID_MASK; - return 0; -} - -static void release_idr(struct idr *idr, struct mutex *lock, int id) -{ - if (lock) - mutex_lock(lock); - idr_remove(idr, id); - if (lock) - mutex_unlock(lock); -} - -/* sys I/F for thermal zone */ - -#define to_thermal_zone(_dev) \ - container_of(_dev, struct thermal_zone_device, device) - -static ssize_t -type_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct thermal_zone_device *tz = to_thermal_zone(dev); - - return sprintf(buf, "%s\n", tz->type); -} - -static ssize_t -temp_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct thermal_zone_device *tz = to_thermal_zone(dev); - - if (!tz->ops->get_temp) - return -EPERM; - - return tz->ops->get_temp(tz, buf); -} - -static ssize_t -mode_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct thermal_zone_device *tz = to_thermal_zone(dev); - - if (!tz->ops->get_mode) - return -EPERM; - - return tz->ops->get_mode(tz, buf); -} - -static ssize_t -mode_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct thermal_zone_device *tz = to_thermal_zone(dev); - int result; - - if (!tz->ops->set_mode) - return -EPERM; - - result = tz->ops->set_mode(tz, buf); - if (result) - return result; - - return count; -} - -static ssize_t -trip_point_type_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct thermal_zone_device *tz = to_thermal_zone(dev); - int trip; - - if (!tz->ops->get_trip_type) - return -EPERM; - - if (!sscanf(attr->attr.name, "trip_point_%d_type", &trip)) - return -EINVAL; - - return tz->ops->get_trip_type(tz, trip, buf); -} - -static ssize_t -trip_point_temp_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct thermal_zone_device *tz = to_thermal_zone(dev); - int trip; - - if (!tz->ops->get_trip_temp) - return -EPERM; - - if (!sscanf(attr->attr.name, "trip_point_%d_temp", &trip)) - return -EINVAL; - - return tz->ops->get_trip_temp(tz, trip, buf); -} - -static DEVICE_ATTR(type, 0444, type_show, NULL); -static DEVICE_ATTR(temp, 0444, temp_show, NULL); -static DEVICE_ATTR(mode, 0644, mode_show, mode_store); - -static struct device_attribute trip_point_attrs[] = { - __ATTR(trip_point_0_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_0_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_1_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_1_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_2_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_2_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_3_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_3_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_4_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_4_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_5_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_5_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_6_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_6_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_7_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_7_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_8_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_8_temp, 0444, trip_point_temp_show, NULL), - __ATTR(trip_point_9_type, 0444, trip_point_type_show, NULL), - __ATTR(trip_point_9_temp, 0444, trip_point_temp_show, NULL), -}; - -#define TRIP_POINT_ATTR_ADD(_dev, _index, result) \ -do { \ - result = device_create_file(_dev, \ - &trip_point_attrs[_index * 2]); \ - if (result) \ - break; \ - result = device_create_file(_dev, \ - &trip_point_attrs[_index * 2 + 1]); \ -} while (0) - -#define TRIP_POINT_ATTR_REMOVE(_dev, _index) \ -do { \ - device_remove_file(_dev, &trip_point_attrs[_index * 2]); \ - device_remove_file(_dev, &trip_point_attrs[_index * 2 + 1]); \ -} while (0) - -/* sys I/F for cooling device */ -#define to_cooling_device(_dev) \ - container_of(_dev, struct thermal_cooling_device, device) - -static ssize_t -thermal_cooling_device_type_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct thermal_cooling_device *cdev = to_cooling_device(dev); - - return sprintf(buf, "%s\n", cdev->type); -} - -static ssize_t -thermal_cooling_device_max_state_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct thermal_cooling_device *cdev = to_cooling_device(dev); - - return cdev->ops->get_max_state(cdev, buf); -} - -static ssize_t -thermal_cooling_device_cur_state_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct thermal_cooling_device *cdev = to_cooling_device(dev); - - return cdev->ops->get_cur_state(cdev, buf); -} - -static ssize_t -thermal_cooling_device_cur_state_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct thermal_cooling_device *cdev = to_cooling_device(dev); - int state; - int result; - - if (!sscanf(buf, "%d\n", &state)) - return -EINVAL; - - if (state < 0) - return -EINVAL; - - result = cdev->ops->set_cur_state(cdev, state); - if (result) - return result; - return count; -} - -static struct device_attribute dev_attr_cdev_type = - __ATTR(type, 0444, thermal_cooling_device_type_show, NULL); -static DEVICE_ATTR(max_state, 0444, - thermal_cooling_device_max_state_show, NULL); -static DEVICE_ATTR(cur_state, 0644, - thermal_cooling_device_cur_state_show, - thermal_cooling_device_cur_state_store); - -static ssize_t -thermal_cooling_device_trip_point_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct thermal_cooling_device_instance *instance; - - instance = - container_of(attr, struct thermal_cooling_device_instance, attr); - - if (instance->trip == THERMAL_TRIPS_NONE) - return sprintf(buf, "-1\n"); - else - return sprintf(buf, "%d\n", instance->trip); -} - -/* Device management */ - -/** - * thermal_zone_bind_cooling_device - bind a cooling device to a thermal zone - * this function is usually called in the thermal zone device .bind callback. - * @tz: thermal zone device - * @trip: indicates which trip point the cooling devices is - * associated with in this thermal zone. - * @cdev: thermal cooling device - */ -int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, - int trip, - struct thermal_cooling_device *cdev) -{ - struct thermal_cooling_device_instance *dev; - struct thermal_cooling_device_instance *pos; - int result; - - if (trip >= tz->trips || - (trip < 0 && trip != THERMAL_TRIPS_NONE)) - return -EINVAL; - - if (!tz || !cdev) - return -EINVAL; - - dev = - kzalloc(sizeof(struct thermal_cooling_device_instance), GFP_KERNEL); - if (!dev) - return -ENOMEM; - dev->tz = tz; - dev->cdev = cdev; - dev->trip = trip; - result = get_idr(&tz->idr, &tz->lock, &dev->id); - if (result) - goto free_mem; - - sprintf(dev->name, "cdev%d", dev->id); - result = - sysfs_create_link(&tz->device.kobj, &cdev->device.kobj, dev->name); - if (result) - goto release_idr; - - sprintf(dev->attr_name, "cdev%d_trip_point", dev->id); - dev->attr.attr.name = dev->attr_name; - dev->attr.attr.mode = 0444; - dev->attr.show = thermal_cooling_device_trip_point_show; - result = device_create_file(&tz->device, &dev->attr); - if (result) - goto remove_symbol_link; - - mutex_lock(&tz->lock); - list_for_each_entry(pos, &tz->cooling_devices, node) - if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) { - result = -EEXIST; - break; - } - if (!result) - list_add_tail(&dev->node, &tz->cooling_devices); - mutex_unlock(&tz->lock); - - if (!result) - return 0; - - device_remove_file(&tz->device, &dev->attr); - remove_symbol_link: - sysfs_remove_link(&tz->device.kobj, dev->name); - release_idr: - release_idr(&tz->idr, &tz->lock, dev->id); - free_mem: - kfree(dev); - return result; -} -EXPORT_SYMBOL(thermal_zone_bind_cooling_device); - -/** - * thermal_zone_unbind_cooling_device - unbind a cooling device from a thermal zone - * this function is usually called in the thermal zone device .unbind callback. - * @tz: thermal zone device - * @trip: indicates which trip point the cooling devices is - * associated with in this thermal zone. - * @cdev: thermal cooling device - */ -int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz, - int trip, - struct thermal_cooling_device *cdev) -{ - struct thermal_cooling_device_instance *pos, *next; - - mutex_lock(&tz->lock); - list_for_each_entry_safe(pos, next, &tz->cooling_devices, node) { - if (pos->tz == tz && pos->trip == trip - && pos->cdev == cdev) { - list_del(&pos->node); - mutex_unlock(&tz->lock); - goto unbind; - } - } - mutex_unlock(&tz->lock); - - return -ENODEV; - - unbind: - device_remove_file(&tz->device, &pos->attr); - sysfs_remove_link(&tz->device.kobj, pos->name); - release_idr(&tz->idr, &tz->lock, pos->id); - kfree(pos); - return 0; -} -EXPORT_SYMBOL(thermal_zone_unbind_cooling_device); - -static void thermal_release(struct device *dev) -{ - struct thermal_zone_device *tz; - struct thermal_cooling_device *cdev; - - if (!strncmp(dev->bus_id, "thermal_zone", sizeof "thermal_zone" - 1)) { - tz = to_thermal_zone(dev); - kfree(tz); - } else { - cdev = to_cooling_device(dev); - kfree(cdev); - } -} - -static struct class thermal_class = { - .name = "thermal", - .dev_release = thermal_release, -}; - -/** - * thermal_cooling_device_register - register a new thermal cooling device - * @type: the thermal cooling device type. - * @devdata: device private data. - * @ops: standard thermal cooling devices callbacks. - */ -struct thermal_cooling_device *thermal_cooling_device_register(char *type, - void *devdata, struct thermal_cooling_device_ops *ops) -{ - struct thermal_cooling_device *cdev; - struct thermal_zone_device *pos; - int result; - - if (strlen(type) >= THERMAL_NAME_LENGTH) - return NULL; - - if (!ops || !ops->get_max_state || !ops->get_cur_state || - !ops->set_cur_state) - return NULL; - - cdev = kzalloc(sizeof(struct thermal_cooling_device), GFP_KERNEL); - if (!cdev) - return NULL; - - result = get_idr(&thermal_cdev_idr, &thermal_idr_lock, &cdev->id); - if (result) { - kfree(cdev); - return NULL; - } - - strcpy(cdev->type, type); - cdev->ops = ops; - cdev->device.class = &thermal_class; - cdev->devdata = devdata; - sprintf(cdev->device.bus_id, "cooling_device%d", cdev->id); - result = device_register(&cdev->device); - if (result) { - release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id); - kfree(cdev); - return NULL; - } - - /* sys I/F */ - if (type) { - result = device_create_file(&cdev->device, - &dev_attr_cdev_type); - if (result) - goto unregister; - } - - result = device_create_file(&cdev->device, &dev_attr_max_state); - if (result) - goto unregister; - - result = device_create_file(&cdev->device, &dev_attr_cur_state); - if (result) - goto unregister; - - mutex_lock(&thermal_list_lock); - list_add(&cdev->node, &thermal_cdev_list); - list_for_each_entry(pos, &thermal_tz_list, node) { - if (!pos->ops->bind) - continue; - result = pos->ops->bind(pos, cdev); - if (result) - break; - - } - mutex_unlock(&thermal_list_lock); - - if (!result) - return cdev; - - unregister: - release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id); - device_unregister(&cdev->device); - return NULL; -} -EXPORT_SYMBOL(thermal_cooling_device_register); - -/** - * thermal_cooling_device_unregister - removes the registered thermal cooling device - * - * @cdev: the thermal cooling device to remove. - * - * thermal_cooling_device_unregister() must be called when the device is no - * longer needed. - */ -void thermal_cooling_device_unregister(struct - thermal_cooling_device - *cdev) -{ - struct thermal_zone_device *tz; - struct thermal_cooling_device *pos = NULL; - - if (!cdev) - return; - - mutex_lock(&thermal_list_lock); - list_for_each_entry(pos, &thermal_cdev_list, node) - if (pos == cdev) - break; - if (pos != cdev) { - /* thermal cooling device not found */ - mutex_unlock(&thermal_list_lock); - return; - } - list_del(&cdev->node); - list_for_each_entry(tz, &thermal_tz_list, node) { - if (!tz->ops->unbind) - continue; - tz->ops->unbind(tz, cdev); - } - mutex_unlock(&thermal_list_lock); - if (cdev->type[0]) - device_remove_file(&cdev->device, - &dev_attr_cdev_type); - device_remove_file(&cdev->device, &dev_attr_max_state); - device_remove_file(&cdev->device, &dev_attr_cur_state); - - release_idr(&thermal_cdev_idr, &thermal_idr_lock, cdev->id); - device_unregister(&cdev->device); - return; -} -EXPORT_SYMBOL(thermal_cooling_device_unregister); - -/** - * thermal_zone_device_register - register a new thermal zone device - * @type: the thermal zone device type - * @trips: the number of trip points the thermal zone support - * @devdata: private device data - * @ops: standard thermal zone device callbacks - * - * thermal_zone_device_unregister() must be called when the device is no - * longer needed. - */ -struct thermal_zone_device *thermal_zone_device_register(char *type, - int trips, void *devdata, - struct thermal_zone_device_ops *ops) -{ - struct thermal_zone_device *tz; - struct thermal_cooling_device *pos; - int result; - int count; - - if (strlen(type) >= THERMAL_NAME_LENGTH) - return NULL; - - if (trips > THERMAL_MAX_TRIPS || trips < 0) - return NULL; - - if (!ops || !ops->get_temp) - return NULL; - - tz = kzalloc(sizeof(struct thermal_zone_device), GFP_KERNEL); - if (!tz) - return NULL; - - INIT_LIST_HEAD(&tz->cooling_devices); - idr_init(&tz->idr); - mutex_init(&tz->lock); - result = get_idr(&thermal_tz_idr, &thermal_idr_lock, &tz->id); - if (result) { - kfree(tz); - return NULL; - } - - strcpy(tz->type, type); - tz->ops = ops; - tz->device.class = &thermal_class; - tz->devdata = devdata; - tz->trips = trips; - sprintf(tz->device.bus_id, "thermal_zone%d", tz->id); - result = device_register(&tz->device); - if (result) { - release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id); - kfree(tz); - return NULL; - } - - /* sys I/F */ - if (type) { - result = device_create_file(&tz->device, &dev_attr_type); - if (result) - goto unregister; - } - - result = device_create_file(&tz->device, &dev_attr_temp); - if (result) - goto unregister; - - if (ops->get_mode) { - result = device_create_file(&tz->device, &dev_attr_mode); - if (result) - goto unregister; - } - - for (count = 0; count < trips; count++) { - TRIP_POINT_ATTR_ADD(&tz->device, count, result); - if (result) - goto unregister; - } - - mutex_lock(&thermal_list_lock); - list_add_tail(&tz->node, &thermal_tz_list); - if (ops->bind) - list_for_each_entry(pos, &thermal_cdev_list, node) { - result = ops->bind(tz, pos); - if (result) - break; - } - mutex_unlock(&thermal_list_lock); - - if (!result) - return tz; - - unregister: - release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id); - device_unregister(&tz->device); - return NULL; -} -EXPORT_SYMBOL(thermal_zone_device_register); - -/** - * thermal_device_unregister - removes the registered thermal zone device - * - * @tz: the thermal zone device to remove - */ -void thermal_zone_device_unregister(struct thermal_zone_device *tz) -{ - struct thermal_cooling_device *cdev; - struct thermal_zone_device *pos = NULL; - int count; - - if (!tz) - return; - - mutex_lock(&thermal_list_lock); - list_for_each_entry(pos, &thermal_tz_list, node) - if (pos == tz) - break; - if (pos != tz) { - /* thermal zone device not found */ - mutex_unlock(&thermal_list_lock); - return; - } - list_del(&tz->node); - if (tz->ops->unbind) - list_for_each_entry(cdev, &thermal_cdev_list, node) - tz->ops->unbind(tz, cdev); - mutex_unlock(&thermal_list_lock); - - if (tz->type[0]) - device_remove_file(&tz->device, &dev_attr_type); - device_remove_file(&tz->device, &dev_attr_temp); - if (tz->ops->get_mode) - device_remove_file(&tz->device, &dev_attr_mode); - - for (count = 0; count < tz->trips; count++) - TRIP_POINT_ATTR_REMOVE(&tz->device, count); - - release_idr(&thermal_tz_idr, &thermal_idr_lock, tz->id); - idr_destroy(&tz->idr); - mutex_destroy(&tz->lock); - device_unregister(&tz->device); - return; -} -EXPORT_SYMBOL(thermal_zone_device_unregister); - -static int __init thermal_init(void) -{ - int result = 0; - - result = class_register(&thermal_class); - if (result) { - idr_destroy(&thermal_tz_idr); - idr_destroy(&thermal_cdev_idr); - mutex_destroy(&thermal_idr_lock); - mutex_destroy(&thermal_list_lock); - } - return result; -} - -static void __exit thermal_exit(void) -{ - class_unregister(&thermal_class); - idr_destroy(&thermal_tz_idr); - idr_destroy(&thermal_cdev_idr); - mutex_destroy(&thermal_idr_lock); - mutex_destroy(&thermal_list_lock); -} - -subsys_initcall(thermal_init); -module_exit(thermal_exit); diff --git a/trunk/include/acpi/acglobal.h b/trunk/include/acpi/acglobal.h index 47a1fd8f2d8a..347a911d8237 100644 --- a/trunk/include/acpi/acglobal.h +++ b/trunk/include/acpi/acglobal.h @@ -117,6 +117,10 @@ extern u32 acpi_dbg_layer; extern u32 acpi_gbl_nesting_level; +/* Event counters */ + +ACPI_EXTERN u32 acpi_gpe_count; + /* Support for dynamic control method tracing mechanism */ ACPI_EXTERN u32 acpi_gbl_original_dbg_level; diff --git a/trunk/include/acpi/acpi_bus.h b/trunk/include/acpi/acpi_bus.h index 504af20b10c1..fb7171b1bd22 100644 --- a/trunk/include/acpi/acpi_bus.h +++ b/trunk/include/acpi/acpi_bus.h @@ -321,8 +321,6 @@ struct acpi_bus_event { extern struct kobject *acpi_kobj; extern int acpi_bus_generate_netlink_event(const char*, const char*, u8, int); -void acpi_bus_private_data_handler(acpi_handle, u32, void *); -int acpi_bus_get_private_data(acpi_handle, void **); /* * External Functions */ diff --git a/trunk/include/acpi/acpi_drivers.h b/trunk/include/acpi/acpi_drivers.h index 581daa451ffc..f85f77a538aa 100644 --- a/trunk/include/acpi/acpi_drivers.h +++ b/trunk/include/acpi/acpi_drivers.h @@ -48,7 +48,6 @@ #define ACPI_BUTTON_HID_SLEEPF "LNXSLPBN" #define ACPI_VIDEO_HID "LNXVIDEO" #define ACPI_BAY_HID "LNXIOBAY" -#define ACPI_DOCK_HID "LNXDOCK" /* -------------------------------------------------------------------------- PCI diff --git a/trunk/include/acpi/acpiosxf.h b/trunk/include/acpi/acpiosxf.h index 1a16cfbe9e0d..ca882b8e7d10 100644 --- a/trunk/include/acpi/acpiosxf.h +++ b/trunk/include/acpi/acpiosxf.h @@ -181,9 +181,6 @@ acpi_os_install_interrupt_handler(u32 gsi, acpi_status acpi_os_remove_interrupt_handler(u32 gsi, acpi_osd_handler service_routine); -void acpi_os_gpe_count(u32 gpe_number); -void acpi_os_fixed_event_count(u32 fixed_event_number); - /* * Threads and Scheduling */ diff --git a/trunk/include/acpi/processor.h b/trunk/include/acpi/processor.h index 0c75a0b9c565..6e253b5b0f3b 100644 --- a/trunk/include/acpi/processor.h +++ b/trunk/include/acpi/processor.h @@ -4,7 +4,7 @@ #include #include #include -#include + #include #define ACPI_PROCESSOR_BUSY_METRIC 10 @@ -34,7 +34,6 @@ #define ACPI_CSTATE_SYSTEMIO (0) #define ACPI_CSTATE_FFH (1) -#define ACPI_CSTATE_HALT (2) /* Power Management */ @@ -65,7 +64,7 @@ struct acpi_processor_cx { u8 valid; u8 type; u32 address; - u8 entry_method; + u8 space_id; u8 index; u32 latency; u32 latency_ticks; @@ -219,7 +218,7 @@ struct acpi_processor { struct acpi_processor_performance *performance; struct acpi_processor_throttling throttling; struct acpi_processor_limit limit; - struct thermal_cooling_device *cdev; + /* the _PDC objects for this processor, if any */ struct acpi_object_list *pdc; }; @@ -331,7 +330,7 @@ extern struct cpuidle_driver acpi_idle_driver; /* in processor_thermal.c */ int acpi_processor_get_limit_info(struct acpi_processor *pr); extern struct file_operations acpi_processor_limit_fops; -extern struct thermal_cooling_device_ops processor_cooling_ops; + #ifdef CONFIG_CPU_FREQ void acpi_thermal_cpufreq_init(void); void acpi_thermal_cpufreq_exit(void); diff --git a/trunk/include/linux/acpi.h b/trunk/include/linux/acpi.h index 5a5a13b64d09..63f2e6ed698f 100644 --- a/trunk/include/linux/acpi.h +++ b/trunk/include/linux/acpi.h @@ -80,6 +80,7 @@ typedef int (*acpi_table_handler) (struct acpi_table_header *table); typedef int (*acpi_table_entry_handler) (struct acpi_subtable_header *header, const unsigned long end); char * __acpi_map_table (unsigned long phys_addr, unsigned long size); +unsigned long acpi_find_rsdp (void); int acpi_boot_init (void); int acpi_boot_table_init (void); int acpi_numa_init (void); @@ -114,9 +115,7 @@ int acpi_unmap_lsapic(int cpu); int acpi_register_ioapic(acpi_handle handle, u64 phys_addr, u32 gsi_base); int acpi_unregister_ioapic(acpi_handle handle, u32 gsi_base); -void acpi_irq_stats_init(void); -extern u32 acpi_irq_handled; extern int acpi_mp_config; extern struct acpi_mcfg_allocation *pci_mmcfg_config; @@ -193,26 +192,6 @@ extern int ec_transaction(u8 command, #endif /*CONFIG_ACPI_EC*/ -#if defined(CONFIG_ACPI_WMI) || defined(CONFIG_ACPI_WMI_MODULE) - -typedef void (*wmi_notify_handler) (u32 value, void *context); - -extern acpi_status wmi_evaluate_method(const char *guid, u8 instance, - u32 method_id, - const struct acpi_buffer *in, - struct acpi_buffer *out); -extern acpi_status wmi_query_block(const char *guid, u8 instance, - struct acpi_buffer *out); -extern acpi_status wmi_set_block(const char *guid, u8 instance, - const struct acpi_buffer *in); -extern acpi_status wmi_install_notify_handler(const char *guid, - wmi_notify_handler handler, void *data); -extern acpi_status wmi_remove_notify_handler(const char *guid); -extern acpi_status wmi_get_event_data(u32 event, struct acpi_buffer *out); -extern bool wmi_has_guid(const char *guid); - -#endif /* CONFIG_ACPI_WMI */ - extern int acpi_blacklisted(void); #ifdef CONFIG_DMI extern void acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d); diff --git a/trunk/include/linux/cpuidle.h b/trunk/include/linux/cpuidle.h index c8eb8c71809e..b0fd85ab9efb 100644 --- a/trunk/include/linux/cpuidle.h +++ b/trunk/include/linux/cpuidle.h @@ -46,10 +46,9 @@ struct cpuidle_state { /* Idle State Flags */ #define CPUIDLE_FLAG_TIME_VALID (0x01) /* is residency time measurable? */ #define CPUIDLE_FLAG_CHECK_BM (0x02) /* BM activity will exit state */ -#define CPUIDLE_FLAG_POLL (0x10) /* no latency, no savings */ -#define CPUIDLE_FLAG_SHALLOW (0x20) /* low latency, minimal savings */ -#define CPUIDLE_FLAG_BALANCED (0x40) /* medium latency, moderate savings */ -#define CPUIDLE_FLAG_DEEP (0x80) /* high latency, large savings */ +#define CPUIDLE_FLAG_SHALLOW (0x10) /* low latency, minimal savings */ +#define CPUIDLE_FLAG_BALANCED (0x20) /* medium latency, moderate savings */ +#define CPUIDLE_FLAG_DEEP (0x40) /* high latency, large savings */ #define CPUIDLE_DRIVER_FLAGS_MASK (0xFFFF0000) @@ -73,19 +72,6 @@ cpuidle_set_statedata(struct cpuidle_state *state, void *data) state->driver_data = data; } -#ifdef CONFIG_SMP -#ifdef CONFIG_ARCH_HAS_CPU_IDLE_WAIT -static inline void cpuidle_kick_cpus(void) -{ - cpu_idle_wait(); -} -#else /* !CONFIG_ARCH_HAS_CPU_IDLE_WAIT */ -#error "Arch needs cpu_idle_wait() equivalent here" -#endif /* !CONFIG_ARCH_HAS_CPU_IDLE_WAIT */ -#else /* !CONFIG_SMP */ -static inline void cpuidle_kick_cpus(void) {} -#endif /* !CONFIG_SMP */ - struct cpuidle_state_kobj { struct cpuidle_state *state; struct completion kobj_unregister; @@ -192,10 +178,4 @@ static inline void cpuidle_unregister_governor(struct cpuidle_governor *gov) { } #endif -#ifdef CONFIG_ARCH_HAS_CPU_RELAX -#define CPUIDLE_DRIVER_STATE_START 1 -#else -#define CPUIDLE_DRIVER_STATE_START 0 -#endif - #endif /* _LINUX_CPUIDLE_H */ diff --git a/trunk/include/linux/dmi.h b/trunk/include/linux/dmi.h index b1251b2af568..5b42a659a308 100644 --- a/trunk/include/linux/dmi.h +++ b/trunk/include/linux/dmi.h @@ -79,6 +79,7 @@ extern void dmi_scan_machine(void); extern int dmi_get_year(int field); extern int dmi_name_in_vendors(const char *str); extern int dmi_available; +extern char *dmi_get_slot(int slot); #else @@ -89,6 +90,7 @@ static inline const struct dmi_device * dmi_find_device(int type, const char *na static inline int dmi_get_year(int year) { return 0; } static inline int dmi_name_in_vendors(const char *s) { return 0; } #define dmi_available 0 +static inline char *dmi_get_slot(int slot) { return NULL; } #endif diff --git a/trunk/include/linux/power_supply.h b/trunk/include/linux/power_supply.h index 68ed19ccf1f7..5cbf3e371012 100644 --- a/trunk/include/linux/power_supply.h +++ b/trunk/include/linux/power_supply.h @@ -94,7 +94,6 @@ enum power_supply_property { /* Properties of type `const char *' */ POWER_SUPPLY_PROP_MODEL_NAME, POWER_SUPPLY_PROP_MANUFACTURER, - POWER_SUPPLY_PROP_SERIAL_NUMBER, }; enum power_supply_type { diff --git a/trunk/include/linux/sonypi.h b/trunk/include/linux/sonypi.h index f41ffd7c2dd9..40c7b5d993b9 100644 --- a/trunk/include/linux/sonypi.h +++ b/trunk/include/linux/sonypi.h @@ -101,8 +101,6 @@ #define SONYPI_EVENT_FNKEY_RELEASED 59 #define SONYPI_EVENT_WIRELESS_ON 60 #define SONYPI_EVENT_WIRELESS_OFF 61 -#define SONYPI_EVENT_ZOOM_IN_PRESSED 62 -#define SONYPI_EVENT_ZOOM_OUT_PRESSED 63 /* get/set brightness */ #define SONYPI_IOCGBRT _IOR('v', 0, __u8) diff --git a/trunk/include/linux/thermal.h b/trunk/include/linux/thermal.h deleted file mode 100644 index bba7712cadc7..000000000000 --- a/trunk/include/linux/thermal.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * thermal.h ($Revision: 0 $) - * - * Copyright (C) 2008 Intel Corp - * Copyright (C) 2008 Zhang Rui - * Copyright (C) 2008 Sujith Thomas - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#ifndef __THERMAL_H__ -#define __THERMAL_H__ - -#include -#include - -struct thermal_zone_device; -struct thermal_cooling_device; - -struct thermal_zone_device_ops { - int (*bind) (struct thermal_zone_device *, - struct thermal_cooling_device *); - int (*unbind) (struct thermal_zone_device *, - struct thermal_cooling_device *); - int (*get_temp) (struct thermal_zone_device *, char *); - int (*get_mode) (struct thermal_zone_device *, char *); - int (*set_mode) (struct thermal_zone_device *, const char *); - int (*get_trip_type) (struct thermal_zone_device *, int, char *); - int (*get_trip_temp) (struct thermal_zone_device *, int, char *); -}; - -struct thermal_cooling_device_ops { - int (*get_max_state) (struct thermal_cooling_device *, char *); - int (*get_cur_state) (struct thermal_cooling_device *, char *); - int (*set_cur_state) (struct thermal_cooling_device *, unsigned int); -}; - -#define THERMAL_TRIPS_NONE -1 -#define THERMAL_MAX_TRIPS 10 -#define THERMAL_NAME_LENGTH 20 -struct thermal_cooling_device { - int id; - char type[THERMAL_NAME_LENGTH]; - struct device device; - void *devdata; - struct thermal_cooling_device_ops *ops; - struct list_head node; -}; - -#define KELVIN_TO_CELSIUS(t) (long)(((long)t-2732 >= 0) ? \ - ((long)t-2732+5)/10 : ((long)t-2732-5)/10) -#define CELSIUS_TO_KELVIN(t) ((t)*10+2732) - -struct thermal_zone_device { - int id; - char type[THERMAL_NAME_LENGTH]; - struct device device; - void *devdata; - int trips; - struct thermal_zone_device_ops *ops; - struct list_head cooling_devices; - struct idr idr; - struct mutex lock; /* protect cooling devices list */ - struct list_head node; -}; - -struct thermal_zone_device *thermal_zone_device_register(char *, int, void *, - struct thermal_zone_device_ops *); -void thermal_zone_device_unregister(struct thermal_zone_device *); - -int thermal_zone_bind_cooling_device(struct thermal_zone_device *, int, - struct thermal_cooling_device *); -int thermal_zone_unbind_cooling_device(struct thermal_zone_device *, int, - struct thermal_cooling_device *); - -struct thermal_cooling_device *thermal_cooling_device_register(char *, void *, - struct thermal_cooling_device_ops *); -void thermal_cooling_device_unregister(struct thermal_cooling_device *); - -#endif /* __THERMAL_H__ */ diff --git a/trunk/kernel/power/Kconfig b/trunk/kernel/power/Kconfig index 79833170bb9c..ef9b802738a5 100644 --- a/trunk/kernel/power/Kconfig +++ b/trunk/kernel/power/Kconfig @@ -74,8 +74,8 @@ config PM_TRACE_RTC RTC across reboots, so that you can debug a machine that just hangs during suspend (or more commonly, during resume). - To use this debugging feature you should attempt to suspend the - machine, reboot it and then run + To use this debugging feature you should attempt to suspend the machine, + then reboot it, then run dmesg -s 1000000 | grep 'hash matches' @@ -123,10 +123,7 @@ config HIBERNATION called "hibernation" in user interfaces. STD checkpoints the system and powers it off; and restores that checkpoint on reboot. - You can suspend your machine with 'echo disk > /sys/power/state' - after placing resume=/dev/swappartition on the kernel command line - in your bootloader's configuration file. - + You can suspend your machine with 'echo disk > /sys/power/state'. Alternatively, you can use the additional userland tools available from .