You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6
* 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-acpi-2.6: (68 commits) ACPI: replace kmalloc+memset with kzalloc ACPI: Add support for acpi_load_table/acpi_unload_table_id fbdev: update after backlight argument change ACPI: video: Add dev argument for backlight_device_register ACPI: Implement acpi_video_get_next_level() ACPI: Kconfig - depend on PM rather than selecting it ACPI: fix NULL check in drivers/acpi/osl.c ACPI: make drivers/acpi/ec.c:ec_ecdt static ACPI: prevent processor module from loading on failures ACPI: fix single linked list manipulation ACPI: ibm_acpi: allow clean removal ACPI: fix git automerge failure ACPI: ibm_acpi: respond to workqueue update ACPI: dock: add uevent to indicate change in device status ACPI: ec: Lindent once again ACPI: ec: Change #define to enums there possible. ACPI: ec: Style changes. ACPI: ec: Acquire Global Lock under EC mutex. ACPI: ec: Drop udelay() from poll mode. Loop by reading status field instead. ACPI: ec: Rename gpe_bit to gpe ...
This commit is contained in:
+126
-37
@@ -398,26 +398,68 @@ Temperature sensors -- /proc/acpi/ibm/thermal
|
||||
|
||||
Most ThinkPads include six or more separate temperature sensors but
|
||||
only expose the CPU temperature through the standard ACPI methods.
|
||||
This feature shows readings from up to eight different sensors. Some
|
||||
readings may not be valid, e.g. may show large negative values. For
|
||||
example, on the X40, a typical output may be:
|
||||
|
||||
temperatures: 42 42 45 41 36 -128 33 -128
|
||||
|
||||
Thomas Gruber took his R51 apart and traced all six active sensors in
|
||||
his laptop (the location of sensors may vary on other models):
|
||||
|
||||
1: CPU
|
||||
2: Mini PCI Module
|
||||
3: HDD
|
||||
4: GPU
|
||||
5: Battery
|
||||
6: N/A
|
||||
7: Battery
|
||||
8: N/A
|
||||
This feature shows readings from up to eight different sensors on older
|
||||
ThinkPads, and it has experimental support for up to sixteen different
|
||||
sensors on newer ThinkPads. Readings from sensors that are not available
|
||||
return -128.
|
||||
|
||||
No commands can be written to this file.
|
||||
|
||||
EXPERIMENTAL: The 16-sensors feature is marked EXPERIMENTAL because the
|
||||
implementation directly accesses hardware registers and may not work as
|
||||
expected. USE WITH CAUTION! To use this feature, you need to supply the
|
||||
experimental=1 parameter when loading the module. When EXPERIMENTAL
|
||||
mode is enabled, reading the first 8 sensors on newer ThinkPads will
|
||||
also use an new experimental thermal sensor access mode.
|
||||
|
||||
For example, on the X40, a typical output may be:
|
||||
temperatures: 42 42 45 41 36 -128 33 -128
|
||||
|
||||
EXPERIMENTAL: On the T43/p, a typical output may be:
|
||||
temperatures: 48 48 36 52 38 -128 31 -128 48 52 48 -128 -128 -128 -128 -128
|
||||
|
||||
The mapping of thermal sensors to physical locations varies depending on
|
||||
system-board model (and thus, on ThinkPad model).
|
||||
|
||||
http://thinkwiki.org/wiki/Thermal_Sensors is a public wiki page that
|
||||
tries to track down these locations for various models.
|
||||
|
||||
Most (newer?) models seem to follow this pattern:
|
||||
|
||||
1: CPU
|
||||
2: (depends on model)
|
||||
3: (depends on model)
|
||||
4: GPU
|
||||
5: Main battery: main sensor
|
||||
6: Bay battery: main sensor
|
||||
7: Main battery: secondary sensor
|
||||
8: Bay battery: secondary sensor
|
||||
9-15: (depends on model)
|
||||
|
||||
For the R51 (source: Thomas Gruber):
|
||||
2: Mini-PCI
|
||||
3: Internal HDD
|
||||
|
||||
For the T43, T43/p (source: Shmidoax/Thinkwiki.org)
|
||||
http://thinkwiki.org/wiki/Thermal_Sensors#ThinkPad_T43.2C_T43p
|
||||
2: System board, left side (near PCMCIA slot), reported as HDAPS temp
|
||||
3: PCMCIA slot
|
||||
9: MCH (northbridge) to DRAM Bus
|
||||
10: ICH (southbridge), under Mini-PCI card, under touchpad
|
||||
11: Power regulator, underside of system board, below F2 key
|
||||
|
||||
The A31 has a very atypical layout for the thermal sensors
|
||||
(source: Milos Popovic, http://thinkwiki.org/wiki/Thermal_Sensors#ThinkPad_A31)
|
||||
1: CPU
|
||||
2: Main Battery: main sensor
|
||||
3: Power Converter
|
||||
4: Bay Battery: main sensor
|
||||
5: MCH (northbridge)
|
||||
6: PCMCIA/ambient
|
||||
7: Main Battery: secondary sensor
|
||||
8: Bay Battery: secondary sensor
|
||||
|
||||
|
||||
EXPERIMENTAL: Embedded controller register dump -- /proc/acpi/ibm/ecdump
|
||||
------------------------------------------------------------------------
|
||||
|
||||
@@ -529,27 +571,57 @@ directly accesses hardware registers and may not work as expected. USE
|
||||
WITH CAUTION! To use this feature, you need to supply the
|
||||
experimental=1 parameter when loading the module.
|
||||
|
||||
This feature attempts to show the current fan speed. The speed is read
|
||||
directly from the hardware registers of the embedded controller. This
|
||||
is known to work on later R, T and X series ThinkPads but may show a
|
||||
bogus value on other models.
|
||||
This feature attempts to show the current fan speed, control mode and
|
||||
other fan data that might be available. The speed is read directly
|
||||
from the hardware registers of the embedded controller. This is known
|
||||
to work on later R, T and X series ThinkPads but may show a bogus
|
||||
value on other models.
|
||||
|
||||
Most ThinkPad fans work in "levels". Level 0 stops the fan. The higher
|
||||
the level, the higher the fan speed, although adjacent levels often map
|
||||
to the same fan speed. 7 is the highest level, where the fan reaches
|
||||
the maximum recommended speed. Level "auto" means the EC changes the
|
||||
fan level according to some internal algorithm, usually based on
|
||||
readings from the thermal sensors. Level "disengaged" means the EC
|
||||
disables the speed-locked closed-loop fan control, and drives the fan as
|
||||
fast as it can go, which might exceed hardware limits, so use this level
|
||||
with caution.
|
||||
|
||||
The fan usually ramps up or down slowly from one speed to another,
|
||||
and it is normal for the EC to take several seconds to react to fan
|
||||
commands.
|
||||
|
||||
The fan may be enabled or disabled with the following commands:
|
||||
|
||||
echo enable >/proc/acpi/ibm/fan
|
||||
echo disable >/proc/acpi/ibm/fan
|
||||
|
||||
WARNING WARNING WARNING: do not leave the fan disabled unless you are
|
||||
monitoring the temperature sensor readings and you are ready to enable
|
||||
it if necessary to avoid overheating.
|
||||
Placing a fan on level 0 is the same as disabling it. Enabling a fan
|
||||
will try to place it in a safe level if it is too slow or disabled.
|
||||
|
||||
The fan only runs if it's enabled *and* the various temperature
|
||||
sensors which control it read high enough. On the X40, this seems to
|
||||
depend on the CPU and HDD temperatures. Specifically, the fan is
|
||||
turned on when either the CPU temperature climbs to 56 degrees or the
|
||||
HDD temperature climbs to 46 degrees. The fan is turned off when the
|
||||
CPU temperature drops to 49 degrees and the HDD temperature drops to
|
||||
41 degrees. These thresholds cannot currently be controlled.
|
||||
WARNING WARNING WARNING: do not leave the fan disabled unless you are
|
||||
monitoring all of the temperature sensor readings and you are ready to
|
||||
enable it if necessary to avoid overheating.
|
||||
|
||||
An enabled fan in level "auto" may stop spinning if the EC decides the
|
||||
ThinkPad is cool enough and doesn't need the extra airflow. This is
|
||||
normal, and the EC will spin the fan up if the varios thermal readings
|
||||
rise too much.
|
||||
|
||||
On the X40, this seems to depend on the CPU and HDD temperatures.
|
||||
Specifically, the fan is turned on when either the CPU temperature
|
||||
climbs to 56 degrees or the HDD temperature climbs to 46 degrees. The
|
||||
fan is turned off when the CPU temperature drops to 49 degrees and the
|
||||
HDD temperature drops to 41 degrees. These thresholds cannot
|
||||
currently be controlled.
|
||||
|
||||
The fan level can be controlled with the command:
|
||||
|
||||
echo 'level <level>' > /proc/acpi/ibm/thermal
|
||||
|
||||
Where <level> is an integer from 0 to 7, or one of the words "auto"
|
||||
or "disengaged" (without the quotes). Not all ThinkPads support the
|
||||
"auto" and "disengaged" levels.
|
||||
|
||||
On the X31 and X40 (and ONLY on those models), the fan speed can be
|
||||
controlled to a certain degree. Once the fan is running, it can be
|
||||
@@ -562,12 +634,9 @@ about 3700 to about 7350. Values outside this range either do not have
|
||||
any effect or the fan speed eventually settles somewhere in that
|
||||
range. The fan cannot be stopped or started with this command.
|
||||
|
||||
On the 570, temperature readings are not available through this
|
||||
feature and the fan control works a little differently. The fan speed
|
||||
is reported in levels from 0 (off) to 7 (max) and can be controlled
|
||||
with the following command:
|
||||
|
||||
echo 'level <level>' > /proc/acpi/ibm/thermal
|
||||
The ThinkPad's ACPI DSDT code will reprogram the fan on its own when
|
||||
certain conditions are met. It will override any fan programming done
|
||||
through ibm-acpi.
|
||||
|
||||
EXPERIMENTAL: WAN -- /proc/acpi/ibm/wan
|
||||
---------------------------------------
|
||||
@@ -601,6 +670,26 @@ example:
|
||||
|
||||
modprobe ibm_acpi hotkey=enable,0xffff video=auto_disable
|
||||
|
||||
The ibm-acpi kernel driver can be programmed to revert the fan level
|
||||
to a safe setting if userspace does not issue one of the fan commands:
|
||||
"enable", "disable", "level" or "watchdog" within a configurable
|
||||
ammount of time. To do this, use the "watchdog" command.
|
||||
|
||||
echo 'watchdog <interval>' > /proc/acpi/ibm/fan
|
||||
|
||||
Interval is the ammount of time in seconds to wait for one of the
|
||||
above mentioned fan commands before reseting the fan level to a safe
|
||||
one. If set to zero, the watchdog is disabled (default). When the
|
||||
watchdog timer runs out, it does the exact equivalent of the "enable"
|
||||
fan command.
|
||||
|
||||
Note that the watchdog timer stops after it enables the fan. It will
|
||||
be rearmed again automatically (using the same interval) when one of
|
||||
the above mentioned fan commands is received. The fan watchdog is,
|
||||
therefore, not suitable to protect against fan mode changes made
|
||||
through means other than the "enable", "disable", and "level" fan
|
||||
commands.
|
||||
|
||||
|
||||
Example Configuration
|
||||
---------------------
|
||||
|
||||
@@ -1400,6 +1400,15 @@ W: http://www.ia64-linux.org/
|
||||
T: git kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git
|
||||
S: Maintained
|
||||
|
||||
IBM ACPI EXTRAS DRIVER
|
||||
P: Henrique de Moraes Holschuh
|
||||
M: ibm-acpi@hmh.eng.br
|
||||
L: ibm-acpi-devel@lists.sourceforge.net
|
||||
W: http://ibm-acpi.sourceforge.net
|
||||
W: http://thinkwiki.org/wiki/Ibm-acpi
|
||||
T: git repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git
|
||||
S: Maintained
|
||||
|
||||
SN-IA64 (Itanium) SUB-PLATFORM
|
||||
P: Jes Sorensen
|
||||
M: jes@sgi.com
|
||||
|
||||
@@ -1327,3 +1327,25 @@ static int __init setup_acpi_sci(char *s)
|
||||
return 0;
|
||||
}
|
||||
early_param("acpi_sci", setup_acpi_sci);
|
||||
|
||||
int __acpi_acquire_global_lock(unsigned int *lock)
|
||||
{
|
||||
unsigned int old, new, val;
|
||||
do {
|
||||
old = *lock;
|
||||
new = (((old & ~0x3) + 2) + ((old >> 1) & 0x1));
|
||||
val = cmpxchg(lock, old, new);
|
||||
} while (unlikely (val != old));
|
||||
return (new < 3) ? -1 : 0;
|
||||
}
|
||||
|
||||
int __acpi_release_global_lock(unsigned int *lock)
|
||||
{
|
||||
unsigned int old, new, val;
|
||||
do {
|
||||
old = *lock;
|
||||
new = old & ~0x3;
|
||||
val = cmpxchg(lock, old, new);
|
||||
} while (unlikely (val != old));
|
||||
return old & 0x1;
|
||||
}
|
||||
|
||||
@@ -276,12 +276,10 @@ acpi_cpufreq_cpu_init (
|
||||
|
||||
dprintk("acpi_cpufreq_cpu_init\n");
|
||||
|
||||
data = kmalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL);
|
||||
data = kzalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL);
|
||||
if (!data)
|
||||
return (-ENOMEM);
|
||||
|
||||
memset(data, 0, sizeof(struct cpufreq_acpi_io));
|
||||
|
||||
acpi_io_data[cpu] = data;
|
||||
|
||||
result = acpi_processor_register_performance(&data->acpi_data, cpu);
|
||||
|
||||
+16
-1
@@ -11,7 +11,7 @@ config ACPI
|
||||
bool "ACPI Support"
|
||||
depends on IA64 || X86
|
||||
depends on PCI
|
||||
select PM
|
||||
depends on PM
|
||||
default y
|
||||
---help---
|
||||
Advanced Configuration and Power Interface (ACPI) support for
|
||||
@@ -97,6 +97,7 @@ config ACPI_BATTERY
|
||||
|
||||
config ACPI_BUTTON
|
||||
tristate "Button"
|
||||
depends on INPUT
|
||||
default y
|
||||
help
|
||||
This driver handles events on the power, sleep and lid buttons.
|
||||
@@ -172,6 +173,7 @@ config ACPI_NUMA
|
||||
config ACPI_ASUS
|
||||
tristate "ASUS/Medion Laptop Extras"
|
||||
depends on X86
|
||||
select BACKLIGHT_CLASS_DEVICE
|
||||
---help---
|
||||
This driver provides support for extra features of ACPI-compatible
|
||||
ASUS laptops. As some of Medion laptops are made by ASUS, it may also
|
||||
@@ -200,6 +202,7 @@ config ACPI_ASUS
|
||||
config ACPI_IBM
|
||||
tristate "IBM ThinkPad Laptop Extras"
|
||||
depends on X86
|
||||
select BACKLIGHT_CLASS_DEVICE
|
||||
---help---
|
||||
This is a Linux ACPI driver for the IBM ThinkPad laptops. It adds
|
||||
support for Fn-Fx key combinations, Bluetooth control, video
|
||||
@@ -222,9 +225,21 @@ config ACPI_IBM_DOCK
|
||||
|
||||
If you are not sure, say N here.
|
||||
|
||||
config ACPI_IBM_BAY
|
||||
bool "Legacy Removable Bay Support"
|
||||
depends on ACPI_IBM
|
||||
depends on ACPI_BAY=n
|
||||
default n
|
||||
---help---
|
||||
Allows the ibm_acpi driver to handle removable bays.
|
||||
This support is obsoleted by CONFIG_ACPI_BAY.
|
||||
|
||||
If you are not sure, say N here.
|
||||
|
||||
config ACPI_TOSHIBA
|
||||
tristate "Toshiba Laptop Extras"
|
||||
depends on X86
|
||||
select BACKLIGHT_CLASS_DEVICE
|
||||
---help---
|
||||
This driver adds support for access to certain system settings
|
||||
on "legacy free" Toshiba laptops. These laptops can be recognized by
|
||||
|
||||
+4
-5
@@ -109,7 +109,7 @@ static struct proc_dir_entry *acpi_ac_dir;
|
||||
|
||||
static int acpi_ac_seq_show(struct seq_file *seq, void *offset)
|
||||
{
|
||||
struct acpi_ac *ac = (struct acpi_ac *)seq->private;
|
||||
struct acpi_ac *ac = seq->private;
|
||||
|
||||
|
||||
if (!ac)
|
||||
@@ -187,7 +187,7 @@ static int acpi_ac_remove_fs(struct acpi_device *device)
|
||||
|
||||
static void acpi_ac_notify(acpi_handle handle, u32 event, void *data)
|
||||
{
|
||||
struct acpi_ac *ac = (struct acpi_ac *)data;
|
||||
struct acpi_ac *ac = data;
|
||||
struct acpi_device *device = NULL;
|
||||
|
||||
|
||||
@@ -221,10 +221,9 @@ static int acpi_ac_add(struct acpi_device *device)
|
||||
if (!device)
|
||||
return -EINVAL;
|
||||
|
||||
ac = kmalloc(sizeof(struct acpi_ac), GFP_KERNEL);
|
||||
ac = kzalloc(sizeof(struct acpi_ac), GFP_KERNEL);
|
||||
if (!ac)
|
||||
return -ENOMEM;
|
||||
memset(ac, 0, sizeof(struct acpi_ac));
|
||||
|
||||
ac->device = device;
|
||||
strcpy(acpi_device_name(device), ACPI_AC_DEVICE_NAME);
|
||||
@@ -269,7 +268,7 @@ static int acpi_ac_remove(struct acpi_device *device, int type)
|
||||
if (!device || !acpi_driver_data(device))
|
||||
return -EINVAL;
|
||||
|
||||
ac = (struct acpi_ac *)acpi_driver_data(device);
|
||||
ac = acpi_driver_data(device);
|
||||
|
||||
status = acpi_remove_notify_handler(device->handle,
|
||||
ACPI_ALL_NOTIFY, acpi_ac_notify);
|
||||
|
||||
@@ -395,10 +395,9 @@ static int acpi_memory_device_add(struct acpi_device *device)
|
||||
if (!device)
|
||||
return -EINVAL;
|
||||
|
||||
mem_device = kmalloc(sizeof(struct acpi_memory_device), GFP_KERNEL);
|
||||
mem_device = kzalloc(sizeof(struct acpi_memory_device), GFP_KERNEL);
|
||||
if (!mem_device)
|
||||
return -ENOMEM;
|
||||
memset(mem_device, 0, sizeof(struct acpi_memory_device));
|
||||
|
||||
INIT_LIST_HEAD(&mem_device->res_list);
|
||||
mem_device->device = device;
|
||||
@@ -429,7 +428,7 @@ static int acpi_memory_device_remove(struct acpi_device *device, int type)
|
||||
if (!device || !acpi_driver_data(device))
|
||||
return -EINVAL;
|
||||
|
||||
mem_device = (struct acpi_memory_device *)acpi_driver_data(device);
|
||||
mem_device = acpi_driver_data(device);
|
||||
kfree(mem_device);
|
||||
|
||||
return 0;
|
||||
|
||||
+49
-21
@@ -35,6 +35,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/backlight.h>
|
||||
#include <acpi/acpi_drivers.h>
|
||||
#include <acpi/acpi_bus.h>
|
||||
#include <asm/uaccess.h>
|
||||
@@ -402,6 +403,8 @@ static struct model_data model_conf[END_MODEL] = {
|
||||
/* procdir we use */
|
||||
static struct proc_dir_entry *asus_proc_dir;
|
||||
|
||||
static struct backlight_device *asus_backlight_device;
|
||||
|
||||
/*
|
||||
* This header is made available to allow proper configuration given model,
|
||||
* revision number , ... this info cannot go in struct asus_hotk because it is
|
||||
@@ -779,7 +782,7 @@ proc_write_lcd(struct file *file, const char __user * buffer,
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int read_brightness(void)
|
||||
static int read_brightness(struct backlight_device *bd)
|
||||
{
|
||||
int value;
|
||||
|
||||
@@ -801,9 +804,10 @@ static int read_brightness(void)
|
||||
/*
|
||||
* Change the brightness level
|
||||
*/
|
||||
static void set_brightness(int value)
|
||||
static int set_brightness(int value)
|
||||
{
|
||||
acpi_status status = 0;
|
||||
int ret = 0;
|
||||
|
||||
/* SPLV laptop */
|
||||
if (hotk->methods->brightness_set) {
|
||||
@@ -811,11 +815,12 @@ static void set_brightness(int value)
|
||||
value, NULL))
|
||||
printk(KERN_WARNING
|
||||
"Asus ACPI: Error changing brightness\n");
|
||||
return;
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* No SPLV method if we are here, act as appropriate */
|
||||
value -= read_brightness();
|
||||
value -= read_brightness(NULL);
|
||||
while (value != 0) {
|
||||
status = acpi_evaluate_object(NULL, (value > 0) ?
|
||||
hotk->methods->brightness_up :
|
||||
@@ -825,15 +830,22 @@ static void set_brightness(int value)
|
||||
if (ACPI_FAILURE(status))
|
||||
printk(KERN_WARNING
|
||||
"Asus ACPI: Error changing brightness\n");
|
||||
ret = -EIO;
|
||||
}
|
||||
return;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int set_brightness_status(struct backlight_device *bd)
|
||||
{
|
||||
return set_brightness(bd->props->brightness);
|
||||
}
|
||||
|
||||
static int
|
||||
proc_read_brn(char *page, char **start, off_t off, int count, int *eof,
|
||||
void *data)
|
||||
{
|
||||
return sprintf(page, "%d\n", read_brightness());
|
||||
return sprintf(page, "%d\n", read_brightness(NULL));
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -1134,7 +1146,7 @@ static int asus_hotk_get_info(void)
|
||||
if (ACPI_FAILURE(status))
|
||||
printk(KERN_WARNING " Couldn't get the DSDT table header\n");
|
||||
else
|
||||
asus_info = (struct acpi_table_header *)dsdt.pointer;
|
||||
asus_info = dsdt.pointer;
|
||||
|
||||
/* We have to write 0 on init this far for all ASUS models */
|
||||
if (!write_acpi_int(hotk->handle, "INIT", 0, &buffer)) {
|
||||
@@ -1156,7 +1168,7 @@ static int asus_hotk_get_info(void)
|
||||
* asus_model_match() and try something completely different.
|
||||
*/
|
||||
if (buffer.pointer) {
|
||||
model = (union acpi_object *)buffer.pointer;
|
||||
model = buffer.pointer;
|
||||
switch (model->type) {
|
||||
case ACPI_TYPE_STRING:
|
||||
string = model->string.pointer;
|
||||
@@ -1252,11 +1264,9 @@ static int asus_hotk_add(struct acpi_device *device)
|
||||
printk(KERN_NOTICE "Asus Laptop ACPI Extras version %s\n",
|
||||
ASUS_ACPI_VERSION);
|
||||
|
||||
hotk =
|
||||
(struct asus_hotk *)kmalloc(sizeof(struct asus_hotk), GFP_KERNEL);
|
||||
hotk = kzalloc(sizeof(struct asus_hotk), GFP_KERNEL);
|
||||
if (!hotk)
|
||||
return -ENOMEM;
|
||||
memset(hotk, 0, sizeof(struct asus_hotk));
|
||||
|
||||
hotk->handle = device->handle;
|
||||
strcpy(acpi_device_name(device), ACPI_HOTK_DEVICE_NAME);
|
||||
@@ -1333,6 +1343,26 @@ static int asus_hotk_remove(struct acpi_device *device, int type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct backlight_properties asus_backlight_data = {
|
||||
.owner = THIS_MODULE,
|
||||
.get_brightness = read_brightness,
|
||||
.update_status = set_brightness_status,
|
||||
.max_brightness = 15,
|
||||
};
|
||||
|
||||
static void __exit asus_acpi_exit(void)
|
||||
{
|
||||
if (asus_backlight_device)
|
||||
backlight_device_unregister(asus_backlight_device);
|
||||
|
||||
acpi_bus_unregister_driver(&asus_hotk_driver);
|
||||
remove_proc_entry(PROC_ASUS, acpi_root_dir);
|
||||
|
||||
kfree(asus_info);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int __init asus_acpi_init(void)
|
||||
{
|
||||
int result;
|
||||
@@ -1370,18 +1400,16 @@ static int __init asus_acpi_init(void)
|
||||
return result;
|
||||
}
|
||||
|
||||
asus_backlight_device = backlight_device_register("asus",NULL,NULL,
|
||||
&asus_backlight_data);
|
||||
if (IS_ERR(asus_backlight_device)) {
|
||||
printk(KERN_ERR "Could not register asus backlight device\n");
|
||||
asus_backlight_device = NULL;
|
||||
asus_acpi_exit();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit asus_acpi_exit(void)
|
||||
{
|
||||
acpi_bus_unregister_driver(&asus_hotk_driver);
|
||||
remove_proc_entry(PROC_ASUS, acpi_root_dir);
|
||||
|
||||
kfree(asus_info);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
module_init(asus_acpi_init);
|
||||
module_exit(asus_acpi_exit);
|
||||
|
||||
+14
-17
@@ -149,7 +149,7 @@ acpi_battery_get_info(struct acpi_battery *battery,
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
package = (union acpi_object *)buffer.pointer;
|
||||
package = buffer.pointer;
|
||||
|
||||
/* Extract Package Data */
|
||||
|
||||
@@ -160,12 +160,11 @@ acpi_battery_get_info(struct acpi_battery *battery,
|
||||
goto end;
|
||||
}
|
||||
|
||||
data.pointer = kmalloc(data.length, GFP_KERNEL);
|
||||
data.pointer = kzalloc(data.length, GFP_KERNEL);
|
||||
if (!data.pointer) {
|
||||
result = -ENOMEM;
|
||||
goto end;
|
||||
}
|
||||
memset(data.pointer, 0, data.length);
|
||||
|
||||
status = acpi_extract_package(package, &format, &data);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
@@ -179,7 +178,7 @@ acpi_battery_get_info(struct acpi_battery *battery,
|
||||
kfree(buffer.pointer);
|
||||
|
||||
if (!result)
|
||||
(*bif) = (struct acpi_battery_info *)data.pointer;
|
||||
(*bif) = data.pointer;
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -209,7 +208,7 @@ acpi_battery_get_status(struct acpi_battery *battery,
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
package = (union acpi_object *)buffer.pointer;
|
||||
package = buffer.pointer;
|
||||
|
||||
/* Extract Package Data */
|
||||
|
||||
@@ -220,12 +219,11 @@ acpi_battery_get_status(struct acpi_battery *battery,
|
||||
goto end;
|
||||
}
|
||||
|
||||
data.pointer = kmalloc(data.length, GFP_KERNEL);
|
||||
data.pointer = kzalloc(data.length, GFP_KERNEL);
|
||||
if (!data.pointer) {
|
||||
result = -ENOMEM;
|
||||
goto end;
|
||||
}
|
||||
memset(data.pointer, 0, data.length);
|
||||
|
||||
status = acpi_extract_package(package, &format, &data);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
@@ -239,7 +237,7 @@ acpi_battery_get_status(struct acpi_battery *battery,
|
||||
kfree(buffer.pointer);
|
||||
|
||||
if (!result)
|
||||
(*bst) = (struct acpi_battery_status *)data.pointer;
|
||||
(*bst) = data.pointer;
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -334,7 +332,7 @@ static struct proc_dir_entry *acpi_battery_dir;
|
||||
static int acpi_battery_read_info(struct seq_file *seq, void *offset)
|
||||
{
|
||||
int result = 0;
|
||||
struct acpi_battery *battery = (struct acpi_battery *)seq->private;
|
||||
struct acpi_battery *battery = seq->private;
|
||||
struct acpi_battery_info *bif = NULL;
|
||||
char *units = "?";
|
||||
|
||||
@@ -418,7 +416,7 @@ static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
|
||||
static int acpi_battery_read_state(struct seq_file *seq, void *offset)
|
||||
{
|
||||
int result = 0;
|
||||
struct acpi_battery *battery = (struct acpi_battery *)seq->private;
|
||||
struct acpi_battery *battery = seq->private;
|
||||
struct acpi_battery_status *bst = NULL;
|
||||
char *units = "?";
|
||||
|
||||
@@ -494,7 +492,7 @@ static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
|
||||
|
||||
static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
|
||||
{
|
||||
struct acpi_battery *battery = (struct acpi_battery *)seq->private;
|
||||
struct acpi_battery *battery = seq->private;
|
||||
char *units = "?";
|
||||
|
||||
|
||||
@@ -531,8 +529,8 @@ acpi_battery_write_alarm(struct file *file,
|
||||
{
|
||||
int result = 0;
|
||||
char alarm_string[12] = { '\0' };
|
||||
struct seq_file *m = (struct seq_file *)file->private_data;
|
||||
struct acpi_battery *battery = (struct acpi_battery *)m->private;
|
||||
struct seq_file *m = file->private_data;
|
||||
struct acpi_battery *battery = m->private;
|
||||
|
||||
|
||||
if (!battery || (count > sizeof(alarm_string) - 1))
|
||||
@@ -658,7 +656,7 @@ static int acpi_battery_remove_fs(struct acpi_device *device)
|
||||
|
||||
static void acpi_battery_notify(acpi_handle handle, u32 event, void *data)
|
||||
{
|
||||
struct acpi_battery *battery = (struct acpi_battery *)data;
|
||||
struct acpi_battery *battery = data;
|
||||
struct acpi_device *device = NULL;
|
||||
|
||||
|
||||
@@ -694,10 +692,9 @@ static int acpi_battery_add(struct acpi_device *device)
|
||||
if (!device)
|
||||
return -EINVAL;
|
||||
|
||||
battery = kmalloc(sizeof(struct acpi_battery), GFP_KERNEL);
|
||||
battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL);
|
||||
if (!battery)
|
||||
return -ENOMEM;
|
||||
memset(battery, 0, sizeof(struct acpi_battery));
|
||||
|
||||
battery->device = device;
|
||||
strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
|
||||
@@ -742,7 +739,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
|
||||
if (!device || !acpi_driver_data(device))
|
||||
return -EINVAL;
|
||||
|
||||
battery = (struct acpi_battery *)acpi_driver_data(device);
|
||||
battery = acpi_driver_data(device);
|
||||
|
||||
status = acpi_remove_notify_handler(device->handle,
|
||||
ACPI_ALL_NOTIFY,
|
||||
|
||||
+138
-85
@@ -29,6 +29,7 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/input.h>
|
||||
#include <acpi/acpi_bus.h>
|
||||
#include <acpi/acpi_drivers.h>
|
||||
|
||||
@@ -62,7 +63,7 @@
|
||||
#define _COMPONENT ACPI_BUTTON_COMPONENT
|
||||
ACPI_MODULE_NAME("acpi_button")
|
||||
|
||||
MODULE_AUTHOR("Paul Diefenbaugh");
|
||||
MODULE_AUTHOR("Paul Diefenbaugh");
|
||||
MODULE_DESCRIPTION(ACPI_BUTTON_DRIVER_NAME);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
@@ -78,12 +79,14 @@ static struct acpi_driver acpi_button_driver = {
|
||||
.ops = {
|
||||
.add = acpi_button_add,
|
||||
.remove = acpi_button_remove,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
struct acpi_button {
|
||||
struct acpi_device *device; /* Fixed button kludge */
|
||||
u8 type;
|
||||
unsigned int type;
|
||||
struct input_dev *input;
|
||||
char phys[32]; /* for input device */
|
||||
unsigned long pushed;
|
||||
};
|
||||
|
||||
@@ -109,8 +112,7 @@ static struct proc_dir_entry *acpi_button_dir;
|
||||
|
||||
static int acpi_button_info_seq_show(struct seq_file *seq, void *offset)
|
||||
{
|
||||
struct acpi_button *button = (struct acpi_button *)seq->private;
|
||||
|
||||
struct acpi_button *button = seq->private;
|
||||
|
||||
if (!button || !button->device)
|
||||
return 0;
|
||||
@@ -128,22 +130,17 @@ static int acpi_button_info_open_fs(struct inode *inode, struct file *file)
|
||||
|
||||
static int acpi_button_state_seq_show(struct seq_file *seq, void *offset)
|
||||
{
|
||||
struct acpi_button *button = (struct acpi_button *)seq->private;
|
||||
struct acpi_button *button = seq->private;
|
||||
acpi_status status;
|
||||
unsigned long state;
|
||||
|
||||
|
||||
if (!button || !button->device)
|
||||
return 0;
|
||||
|
||||
status = acpi_evaluate_integer(button->device->handle, "_LID", NULL, &state);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
seq_printf(seq, "state: unsupported\n");
|
||||
} else {
|
||||
seq_printf(seq, "state: %s\n",
|
||||
(state ? "open" : "closed"));
|
||||
}
|
||||
|
||||
seq_printf(seq, "state: %s\n",
|
||||
ACPI_FAILURE(status) ? "unsupported" :
|
||||
(state ? "open" : "closed"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -159,8 +156,7 @@ static struct proc_dir_entry *acpi_lid_dir;
|
||||
static int acpi_button_add_fs(struct acpi_device *device)
|
||||
{
|
||||
struct proc_dir_entry *entry = NULL;
|
||||
struct acpi_button *button = NULL;
|
||||
|
||||
struct acpi_button *button;
|
||||
|
||||
if (!device || !acpi_driver_data(device))
|
||||
return -EINVAL;
|
||||
@@ -228,10 +224,8 @@ static int acpi_button_add_fs(struct acpi_device *device)
|
||||
|
||||
static int acpi_button_remove_fs(struct acpi_device *device)
|
||||
{
|
||||
struct acpi_button *button = NULL;
|
||||
struct acpi_button *button = acpi_driver_data(device);
|
||||
|
||||
|
||||
button = acpi_driver_data(device);
|
||||
if (acpi_device_dir(device)) {
|
||||
if (button->type == ACPI_BUTTON_TYPE_LID)
|
||||
remove_proc_entry(ACPI_BUTTON_FILE_STATE,
|
||||
@@ -253,14 +247,34 @@ static int acpi_button_remove_fs(struct acpi_device *device)
|
||||
|
||||
static void acpi_button_notify(acpi_handle handle, u32 event, void *data)
|
||||
{
|
||||
struct acpi_button *button = (struct acpi_button *)data;
|
||||
|
||||
struct acpi_button *button = data;
|
||||
struct input_dev *input;
|
||||
|
||||
if (!button || !button->device)
|
||||
return;
|
||||
|
||||
switch (event) {
|
||||
case ACPI_BUTTON_NOTIFY_STATUS:
|
||||
input = button->input;
|
||||
|
||||
if (button->type == ACPI_BUTTON_TYPE_LID) {
|
||||
struct acpi_handle *handle = button->device->handle;
|
||||
unsigned long state;
|
||||
|
||||
if (!ACPI_FAILURE(acpi_evaluate_integer(handle, "_LID",
|
||||
NULL, &state)))
|
||||
input_report_switch(input, SW_LID, !state);
|
||||
|
||||
} else {
|
||||
int keycode = test_bit(KEY_SLEEP, input->keybit) ?
|
||||
KEY_SLEEP : KEY_POWER;
|
||||
|
||||
input_report_key(input, keycode, 1);
|
||||
input_sync(input);
|
||||
input_report_key(input, keycode, 0);
|
||||
}
|
||||
input_sync(input);
|
||||
|
||||
acpi_bus_generate_event(button->device, event,
|
||||
++button->pushed);
|
||||
break;
|
||||
@@ -275,8 +289,7 @@ static void acpi_button_notify(acpi_handle handle, u32 event, void *data)
|
||||
|
||||
static acpi_status acpi_button_notify_fixed(void *data)
|
||||
{
|
||||
struct acpi_button *button = (struct acpi_button *)data;
|
||||
|
||||
struct acpi_button *button = data;
|
||||
|
||||
if (!button)
|
||||
return AE_BAD_PARAMETER;
|
||||
@@ -286,24 +299,75 @@ static acpi_status acpi_button_notify_fixed(void *data)
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
static int acpi_button_install_notify_handlers(struct acpi_button *button)
|
||||
{
|
||||
acpi_status status;
|
||||
|
||||
switch (button->type) {
|
||||
case ACPI_BUTTON_TYPE_POWERF:
|
||||
status =
|
||||
acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
|
||||
acpi_button_notify_fixed,
|
||||
button);
|
||||
break;
|
||||
case ACPI_BUTTON_TYPE_SLEEPF:
|
||||
status =
|
||||
acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
|
||||
acpi_button_notify_fixed,
|
||||
button);
|
||||
break;
|
||||
default:
|
||||
status = acpi_install_notify_handler(button->device->handle,
|
||||
ACPI_DEVICE_NOTIFY,
|
||||
acpi_button_notify,
|
||||
button);
|
||||
break;
|
||||
}
|
||||
|
||||
return ACPI_FAILURE(status) ? -ENODEV : 0;
|
||||
}
|
||||
|
||||
static void acpi_button_remove_notify_handlers(struct acpi_button *button)
|
||||
{
|
||||
switch (button->type) {
|
||||
case ACPI_BUTTON_TYPE_POWERF:
|
||||
acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
|
||||
acpi_button_notify_fixed);
|
||||
break;
|
||||
case ACPI_BUTTON_TYPE_SLEEPF:
|
||||
acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
|
||||
acpi_button_notify_fixed);
|
||||
break;
|
||||
default:
|
||||
acpi_remove_notify_handler(button->device->handle,
|
||||
ACPI_DEVICE_NOTIFY,
|
||||
acpi_button_notify);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int acpi_button_add(struct acpi_device *device)
|
||||
{
|
||||
int result = 0;
|
||||
acpi_status status = AE_OK;
|
||||
struct acpi_button *button = NULL;
|
||||
|
||||
int error;
|
||||
struct acpi_button *button;
|
||||
struct input_dev *input;
|
||||
|
||||
if (!device)
|
||||
return -EINVAL;
|
||||
|
||||
button = kmalloc(sizeof(struct acpi_button), GFP_KERNEL);
|
||||
button = kzalloc(sizeof(struct acpi_button), GFP_KERNEL);
|
||||
if (!button)
|
||||
return -ENOMEM;
|
||||
memset(button, 0, sizeof(struct acpi_button));
|
||||
|
||||
button->device = device;
|
||||
acpi_driver_data(device) = button;
|
||||
|
||||
button->input = input = input_allocate_device();
|
||||
if (!input) {
|
||||
error = -ENOMEM;
|
||||
goto err_free_button;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine the button type (via hid), as fixed-feature buttons
|
||||
* need to be handled a bit differently than generic-space.
|
||||
@@ -338,39 +402,48 @@ static int acpi_button_add(struct acpi_device *device)
|
||||
} else {
|
||||
printk(KERN_ERR PREFIX "Unsupported hid [%s]\n",
|
||||
acpi_device_hid(device));
|
||||
result = -ENODEV;
|
||||
goto end;
|
||||
error = -ENODEV;
|
||||
goto err_free_input;
|
||||
}
|
||||
|
||||
result = acpi_button_add_fs(device);
|
||||
if (result)
|
||||
goto end;
|
||||
error = acpi_button_add_fs(device);
|
||||
if (error)
|
||||
goto err_free_input;
|
||||
|
||||
error = acpi_button_install_notify_handlers(button);
|
||||
if (error)
|
||||
goto err_remove_fs;
|
||||
|
||||
snprintf(button->phys, sizeof(button->phys),
|
||||
"%s/button/input0", acpi_device_hid(device));
|
||||
|
||||
input->name = acpi_device_name(device);
|
||||
input->phys = button->phys;
|
||||
input->id.bustype = BUS_HOST;
|
||||
input->id.product = button->type;
|
||||
|
||||
switch (button->type) {
|
||||
case ACPI_BUTTON_TYPE_POWER:
|
||||
case ACPI_BUTTON_TYPE_POWERF:
|
||||
status =
|
||||
acpi_install_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
|
||||
acpi_button_notify_fixed,
|
||||
button);
|
||||
input->evbit[0] = BIT(EV_KEY);
|
||||
set_bit(KEY_POWER, input->keybit);
|
||||
break;
|
||||
|
||||
case ACPI_BUTTON_TYPE_SLEEP:
|
||||
case ACPI_BUTTON_TYPE_SLEEPF:
|
||||
status =
|
||||
acpi_install_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
|
||||
acpi_button_notify_fixed,
|
||||
button);
|
||||
input->evbit[0] = BIT(EV_KEY);
|
||||
set_bit(KEY_SLEEP, input->keybit);
|
||||
break;
|
||||
default:
|
||||
status = acpi_install_notify_handler(device->handle,
|
||||
ACPI_DEVICE_NOTIFY,
|
||||
acpi_button_notify,
|
||||
button);
|
||||
|
||||
case ACPI_BUTTON_TYPE_LID:
|
||||
input->evbit[0] = BIT(EV_SW);
|
||||
set_bit(SW_LID, input->swbit);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ACPI_FAILURE(status)) {
|
||||
result = -ENODEV;
|
||||
goto end;
|
||||
}
|
||||
error = input_register_device(input);
|
||||
if (error)
|
||||
goto err_remove_handlers;
|
||||
|
||||
if (device->wakeup.flags.valid) {
|
||||
/* Button's GPE is run-wake GPE */
|
||||
@@ -385,47 +458,31 @@ static int acpi_button_add(struct acpi_device *device)
|
||||
printk(KERN_INFO PREFIX "%s [%s]\n",
|
||||
acpi_device_name(device), acpi_device_bid(device));
|
||||
|
||||
end:
|
||||
if (result) {
|
||||
acpi_button_remove_fs(device);
|
||||
kfree(button);
|
||||
}
|
||||
return 0;
|
||||
|
||||
return result;
|
||||
err_remove_handlers:
|
||||
acpi_button_remove_notify_handlers(button);
|
||||
err_remove_fs:
|
||||
acpi_button_remove_fs(device);
|
||||
err_free_input:
|
||||
input_free_device(input);
|
||||
err_free_button:
|
||||
kfree(button);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int acpi_button_remove(struct acpi_device *device, int type)
|
||||
{
|
||||
acpi_status status = 0;
|
||||
struct acpi_button *button = NULL;
|
||||
|
||||
struct acpi_button *button;
|
||||
|
||||
if (!device || !acpi_driver_data(device))
|
||||
return -EINVAL;
|
||||
|
||||
button = acpi_driver_data(device);
|
||||
|
||||
/* Unregister for device notifications. */
|
||||
switch (button->type) {
|
||||
case ACPI_BUTTON_TYPE_POWERF:
|
||||
status =
|
||||
acpi_remove_fixed_event_handler(ACPI_EVENT_POWER_BUTTON,
|
||||
acpi_button_notify_fixed);
|
||||
break;
|
||||
case ACPI_BUTTON_TYPE_SLEEPF:
|
||||
status =
|
||||
acpi_remove_fixed_event_handler(ACPI_EVENT_SLEEP_BUTTON,
|
||||
acpi_button_notify_fixed);
|
||||
break;
|
||||
default:
|
||||
status = acpi_remove_notify_handler(device->handle,
|
||||
ACPI_DEVICE_NOTIFY,
|
||||
acpi_button_notify);
|
||||
break;
|
||||
}
|
||||
|
||||
acpi_button_remove_notify_handlers(button);
|
||||
acpi_button_remove_fs(device);
|
||||
|
||||
input_unregister_device(button->input);
|
||||
kfree(button);
|
||||
|
||||
return 0;
|
||||
@@ -433,8 +490,7 @@ static int acpi_button_remove(struct acpi_device *device, int type)
|
||||
|
||||
static int __init acpi_button_init(void)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
int result;
|
||||
|
||||
acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir);
|
||||
if (!acpi_button_dir)
|
||||
@@ -451,7 +507,6 @@ static int __init acpi_button_init(void)
|
||||
|
||||
static void __exit acpi_button_exit(void)
|
||||
{
|
||||
|
||||
acpi_bus_unregister_driver(&acpi_button_driver);
|
||||
|
||||
if (acpi_power_dir)
|
||||
@@ -461,8 +516,6 @@ static void __exit acpi_button_exit(void)
|
||||
if (acpi_lid_dir)
|
||||
remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
|
||||
remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
module_init(acpi_button_init);
|
||||
|
||||
@@ -96,11 +96,10 @@ static int acpi_container_add(struct acpi_device *device)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
container = kmalloc(sizeof(struct acpi_container), GFP_KERNEL);
|
||||
container = kzalloc(sizeof(struct acpi_container), GFP_KERNEL);
|
||||
if (!container)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(container, 0, sizeof(struct acpi_container));
|
||||
container->handle = device->handle;
|
||||
strcpy(acpi_device_name(device), ACPI_CONTAINER_DEVICE_NAME);
|
||||
strcpy(acpi_device_class(device), ACPI_CONTAINER_CLASS);
|
||||
@@ -117,7 +116,7 @@ static int acpi_container_remove(struct acpi_device *device, int type)
|
||||
acpi_status status = AE_OK;
|
||||
struct acpi_container *pc = NULL;
|
||||
|
||||
pc = (struct acpi_container *)acpi_driver_data(device);
|
||||
pc = acpi_driver_data(device);
|
||||
kfree(pc);
|
||||
return status;
|
||||
}
|
||||
|
||||
+121
-32
@@ -27,6 +27,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <acpi/acpi_bus.h>
|
||||
#include <acpi/acpi_drivers.h>
|
||||
@@ -39,13 +40,15 @@ MODULE_DESCRIPTION(ACPI_DOCK_DRIVER_NAME);
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static struct atomic_notifier_head dock_notifier_list;
|
||||
static struct platform_device dock_device;
|
||||
static char dock_device_name[] = "dock";
|
||||
|
||||
struct dock_station {
|
||||
acpi_handle handle;
|
||||
unsigned long last_dock_time;
|
||||
u32 flags;
|
||||
spinlock_t dd_lock;
|
||||
spinlock_t hp_lock;
|
||||
struct mutex hp_lock;
|
||||
struct list_head dependent_devices;
|
||||
struct list_head hotplug_devices;
|
||||
};
|
||||
@@ -115,9 +118,9 @@ static void
|
||||
dock_add_hotplug_device(struct dock_station *ds,
|
||||
struct dock_dependent_device *dd)
|
||||
{
|
||||
spin_lock(&ds->hp_lock);
|
||||
mutex_lock(&ds->hp_lock);
|
||||
list_add_tail(&dd->hotplug_list, &ds->hotplug_devices);
|
||||
spin_unlock(&ds->hp_lock);
|
||||
mutex_unlock(&ds->hp_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,9 +134,9 @@ static void
|
||||
dock_del_hotplug_device(struct dock_station *ds,
|
||||
struct dock_dependent_device *dd)
|
||||
{
|
||||
spin_lock(&ds->hp_lock);
|
||||
mutex_lock(&ds->hp_lock);
|
||||
list_del(&dd->hotplug_list);
|
||||
spin_unlock(&ds->hp_lock);
|
||||
mutex_unlock(&ds->hp_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -296,7 +299,7 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event)
|
||||
{
|
||||
struct dock_dependent_device *dd;
|
||||
|
||||
spin_lock(&ds->hp_lock);
|
||||
mutex_lock(&ds->hp_lock);
|
||||
|
||||
/*
|
||||
* First call driver specific hotplug functions
|
||||
@@ -318,15 +321,17 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event)
|
||||
else
|
||||
dock_create_acpi_device(dd->handle);
|
||||
}
|
||||
spin_unlock(&ds->hp_lock);
|
||||
mutex_unlock(&ds->hp_lock);
|
||||
}
|
||||
|
||||
static void dock_event(struct dock_station *ds, u32 event, int num)
|
||||
{
|
||||
struct device *dev = &dock_device.dev;
|
||||
/*
|
||||
* we don't do events until someone tells me that
|
||||
* they would like to have them.
|
||||
* Indicate that the status of the dock station has
|
||||
* changed.
|
||||
*/
|
||||
kobject_uevent(&dev->kobj, KOBJ_CHANGE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -441,6 +446,9 @@ static int dock_in_progress(struct dock_station *ds)
|
||||
*/
|
||||
int register_dock_notifier(struct notifier_block *nb)
|
||||
{
|
||||
if (!dock_station)
|
||||
return -ENODEV;
|
||||
|
||||
return atomic_notifier_chain_register(&dock_notifier_list, nb);
|
||||
}
|
||||
|
||||
@@ -452,6 +460,9 @@ EXPORT_SYMBOL_GPL(register_dock_notifier);
|
||||
*/
|
||||
void unregister_dock_notifier(struct notifier_block *nb)
|
||||
{
|
||||
if (!dock_station)
|
||||
return;
|
||||
|
||||
atomic_notifier_chain_unregister(&dock_notifier_list, nb);
|
||||
}
|
||||
|
||||
@@ -511,6 +522,37 @@ void unregister_hotplug_dock_device(acpi_handle handle)
|
||||
|
||||
EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device);
|
||||
|
||||
/**
|
||||
* handle_eject_request - handle an undock request checking for error conditions
|
||||
*
|
||||
* Check to make sure the dock device is still present, then undock and
|
||||
* hotremove all the devices that may need removing.
|
||||
*/
|
||||
static int handle_eject_request(struct dock_station *ds, u32 event)
|
||||
{
|
||||
if (!dock_present(ds))
|
||||
return -ENODEV;
|
||||
|
||||
if (dock_in_progress(ds))
|
||||
return -EBUSY;
|
||||
|
||||
/*
|
||||
* here we need to generate the undock
|
||||
* event prior to actually doing the undock
|
||||
* so that the device struct still exists.
|
||||
*/
|
||||
dock_event(ds, event, UNDOCK_EVENT);
|
||||
hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST);
|
||||
undock(ds);
|
||||
eject_dock(ds);
|
||||
if (dock_present(ds)) {
|
||||
printk(KERN_ERR PREFIX "Unable to undock!\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* dock_notify - act upon an acpi dock notification
|
||||
* @handle: the dock station handle
|
||||
@@ -519,13 +561,11 @@ EXPORT_SYMBOL_GPL(unregister_hotplug_dock_device);
|
||||
*
|
||||
* If we are notified to dock, then check to see if the dock is
|
||||
* present and then dock. Notify all drivers of the dock event,
|
||||
* and then hotplug and devices that may need hotplugging. For undock
|
||||
* check to make sure the dock device is still present, then undock
|
||||
* and hotremove all the devices that may need removing.
|
||||
* and then hotplug and devices that may need hotplugging.
|
||||
*/
|
||||
static void dock_notify(acpi_handle handle, u32 event, void *data)
|
||||
{
|
||||
struct dock_station *ds = (struct dock_station *)data;
|
||||
struct dock_station *ds = data;
|
||||
|
||||
switch (event) {
|
||||
case ACPI_NOTIFY_BUS_CHECK:
|
||||
@@ -553,19 +593,7 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
|
||||
* to the driver who wish to hotplug.
|
||||
*/
|
||||
case ACPI_NOTIFY_EJECT_REQUEST:
|
||||
if (!dock_in_progress(ds) && dock_present(ds)) {
|
||||
/*
|
||||
* here we need to generate the undock
|
||||
* event prior to actually doing the undock
|
||||
* so that the device struct still exists.
|
||||
*/
|
||||
dock_event(ds, event, UNDOCK_EVENT);
|
||||
hotplug_dock_devices(ds, ACPI_NOTIFY_EJECT_REQUEST);
|
||||
undock(ds);
|
||||
eject_dock(ds);
|
||||
if (dock_present(ds))
|
||||
printk(KERN_ERR PREFIX "Unable to undock!\n");
|
||||
}
|
||||
handle_eject_request(ds, event);
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR PREFIX "Unknown dock event %d\n", event);
|
||||
@@ -588,7 +616,7 @@ find_dock_devices(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
{
|
||||
acpi_status status;
|
||||
acpi_handle tmp;
|
||||
struct dock_station *ds = (struct dock_station *)context;
|
||||
struct dock_station *ds = context;
|
||||
struct dock_dependent_device *dd;
|
||||
|
||||
status = acpi_bus_get_ejd(handle, &tmp);
|
||||
@@ -604,6 +632,33 @@ find_dock_devices(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* show_docked - read method for "docked" file in sysfs
|
||||
*/
|
||||
static ssize_t show_docked(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", dock_present(dock_station));
|
||||
|
||||
}
|
||||
DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL);
|
||||
|
||||
/*
|
||||
* write_undock - write method for "undock" file in sysfs
|
||||
*/
|
||||
static ssize_t write_undock(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!count)
|
||||
return -EINVAL;
|
||||
|
||||
ret = handle_eject_request(dock_station, ACPI_NOTIFY_EJECT_REQUEST);
|
||||
return ret ? ret: count;
|
||||
}
|
||||
DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock);
|
||||
|
||||
/**
|
||||
* dock_add - add a new dock station
|
||||
* @handle: the dock station handle
|
||||
@@ -626,9 +681,33 @@ static int dock_add(acpi_handle handle)
|
||||
INIT_LIST_HEAD(&dock_station->dependent_devices);
|
||||
INIT_LIST_HEAD(&dock_station->hotplug_devices);
|
||||
spin_lock_init(&dock_station->dd_lock);
|
||||
spin_lock_init(&dock_station->hp_lock);
|
||||
mutex_init(&dock_station->hp_lock);
|
||||
ATOMIC_INIT_NOTIFIER_HEAD(&dock_notifier_list);
|
||||
|
||||
/* initialize platform device stuff */
|
||||
dock_device.name = dock_device_name;
|
||||
ret = platform_device_register(&dock_device);
|
||||
if (ret) {
|
||||
printk(KERN_ERR PREFIX "Error %d registering dock device\n", ret);
|
||||
kfree(dock_station);
|
||||
return ret;
|
||||
}
|
||||
ret = device_create_file(&dock_device.dev, &dev_attr_docked);
|
||||
if (ret) {
|
||||
printk("Error %d adding sysfs file\n", ret);
|
||||
platform_device_unregister(&dock_device);
|
||||
kfree(dock_station);
|
||||
return ret;
|
||||
}
|
||||
ret = device_create_file(&dock_device.dev, &dev_attr_undock);
|
||||
if (ret) {
|
||||
printk("Error %d adding sysfs file\n", ret);
|
||||
device_remove_file(&dock_device.dev, &dev_attr_docked);
|
||||
platform_device_unregister(&dock_device);
|
||||
kfree(dock_station);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Find dependent devices */
|
||||
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
|
||||
ACPI_UINT32_MAX, find_dock_devices, dock_station,
|
||||
@@ -638,7 +717,8 @@ static int dock_add(acpi_handle handle)
|
||||
dd = alloc_dock_dependent_device(handle);
|
||||
if (!dd) {
|
||||
kfree(dock_station);
|
||||
return -ENOMEM;
|
||||
ret = -ENOMEM;
|
||||
goto dock_add_err_unregister;
|
||||
}
|
||||
add_dock_dependent_device(dock_station, dd);
|
||||
|
||||
@@ -658,8 +738,12 @@ static int dock_add(acpi_handle handle)
|
||||
return 0;
|
||||
|
||||
dock_add_err:
|
||||
kfree(dock_station);
|
||||
kfree(dd);
|
||||
dock_add_err_unregister:
|
||||
device_remove_file(&dock_device.dev, &dev_attr_docked);
|
||||
device_remove_file(&dock_device.dev, &dev_attr_undock);
|
||||
platform_device_unregister(&dock_device);
|
||||
kfree(dock_station);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -686,6 +770,11 @@ static int dock_remove(void)
|
||||
if (ACPI_FAILURE(status))
|
||||
printk(KERN_ERR "Error removing notify handler\n");
|
||||
|
||||
/* cleanup sysfs */
|
||||
device_remove_file(&dock_device.dev, &dev_attr_docked);
|
||||
device_remove_file(&dock_device.dev, &dev_attr_undock);
|
||||
platform_device_unregister(&dock_device);
|
||||
|
||||
/* free dock station memory */
|
||||
kfree(dock_station);
|
||||
return 0;
|
||||
@@ -703,7 +792,7 @@ static int dock_remove(void)
|
||||
static acpi_status
|
||||
find_dock(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
{
|
||||
int *count = (int *)context;
|
||||
int *count = context;
|
||||
acpi_status status = AE_OK;
|
||||
|
||||
if (is_dock(handle)) {
|
||||
@@ -726,7 +815,7 @@ static int __init dock_init(void)
|
||||
ACPI_UINT32_MAX, find_dock, &num, NULL);
|
||||
|
||||
if (!num)
|
||||
return -ENODEV;
|
||||
printk(KERN_INFO "No dock devices found.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+158
-198
File diff suppressed because it is too large
Load Diff
@@ -331,7 +331,6 @@ static void ACPI_SYSTEM_XFACE acpi_ev_global_lock_thread(void *context)
|
||||
static u32 acpi_ev_global_lock_handler(void *context)
|
||||
{
|
||||
u8 acquired = FALSE;
|
||||
acpi_status status;
|
||||
|
||||
/*
|
||||
* Attempt to get the lock
|
||||
|
||||
@@ -266,10 +266,10 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
|
||||
walk_state->thread->thread_id)
|
||||
&& (obj_desc->mutex.os_mutex != ACPI_GLOBAL_LOCK)) {
|
||||
ACPI_ERROR((AE_INFO,
|
||||
"Thread %X cannot release Mutex [%4.4s] acquired by thread %X",
|
||||
(u32) walk_state->thread->thread_id,
|
||||
"Thread %lX cannot release Mutex [%4.4s] acquired by thread %lX",
|
||||
(unsigned long)walk_state->thread->thread_id,
|
||||
acpi_ut_get_node_name(obj_desc->mutex.node),
|
||||
(u32) obj_desc->mutex.owner_thread->thread_id));
|
||||
(unsigned long)obj_desc->mutex.owner_thread->thread_id));
|
||||
return_ACPI_STATUS(AE_AML_NOT_OWNER);
|
||||
}
|
||||
|
||||
|
||||
+4
-5
@@ -99,8 +99,8 @@ acpi_fan_write_state(struct file *file, const char __user * buffer,
|
||||
size_t count, loff_t * ppos)
|
||||
{
|
||||
int result = 0;
|
||||
struct seq_file *m = (struct seq_file *)file->private_data;
|
||||
struct acpi_fan *fan = (struct acpi_fan *)m->private;
|
||||
struct seq_file *m = file->private_data;
|
||||
struct acpi_fan *fan = m->private;
|
||||
char state_string[12] = { '\0' };
|
||||
|
||||
|
||||
@@ -186,10 +186,9 @@ static int acpi_fan_add(struct acpi_device *device)
|
||||
if (!device)
|
||||
return -EINVAL;
|
||||
|
||||
fan = kmalloc(sizeof(struct acpi_fan), GFP_KERNEL);
|
||||
fan = kzalloc(sizeof(struct acpi_fan), GFP_KERNEL);
|
||||
if (!fan)
|
||||
return -ENOMEM;
|
||||
memset(fan, 0, sizeof(struct acpi_fan));
|
||||
|
||||
fan->device = device;
|
||||
strcpy(acpi_device_name(device), "Fan");
|
||||
@@ -229,7 +228,7 @@ static int acpi_fan_remove(struct acpi_device *device, int type)
|
||||
if (!device || !acpi_driver_data(device))
|
||||
return -EINVAL;
|
||||
|
||||
fan = (struct acpi_fan *)acpi_driver_data(device);
|
||||
fan = acpi_driver_data(device);
|
||||
|
||||
acpi_fan_remove_fs(device);
|
||||
|
||||
|
||||
+7
-3
@@ -96,7 +96,7 @@ struct acpi_find_pci_root {
|
||||
static acpi_status
|
||||
do_root_bridge_busnr_callback(struct acpi_resource *resource, void *data)
|
||||
{
|
||||
unsigned long *busnr = (unsigned long *)data;
|
||||
unsigned long *busnr = data;
|
||||
struct acpi_resource_address64 address;
|
||||
|
||||
if (resource->type != ACPI_RESOURCE_TYPE_ADDRESS16 &&
|
||||
@@ -189,8 +189,12 @@ find_pci_rootbridge(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
bus = tmp;
|
||||
|
||||
if (seg == find->seg && bus == find->bus)
|
||||
{
|
||||
find->handle = handle;
|
||||
status = AE_OK;
|
||||
status = AE_CTRL_TERMINATE;
|
||||
}
|
||||
else
|
||||
status = AE_OK;
|
||||
exit:
|
||||
kfree(buffer.pointer);
|
||||
return status;
|
||||
@@ -217,7 +221,7 @@ do_acpi_find_child(acpi_handle handle, u32 lvl, void *context, void **rv)
|
||||
acpi_status status;
|
||||
struct acpi_device_info *info;
|
||||
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
|
||||
struct acpi_find_child *find = (struct acpi_find_child *)context;
|
||||
struct acpi_find_child *find = context;
|
||||
|
||||
status = acpi_get_object_info(handle, &buffer);
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
|
||||
@@ -265,8 +265,7 @@ static char *format_result(union acpi_object *object)
|
||||
|
||||
static int hotkey_polling_seq_show(struct seq_file *seq, void *offset)
|
||||
{
|
||||
struct acpi_polling_hotkey *poll_hotkey =
|
||||
(struct acpi_polling_hotkey *)seq->private;
|
||||
struct acpi_polling_hotkey *poll_hotkey = seq->private;
|
||||
char *buf;
|
||||
|
||||
|
||||
@@ -577,7 +576,7 @@ init_poll_hotkey_device(union acpi_hotkey *key, char **config_entry,
|
||||
if (ACPI_FAILURE(status))
|
||||
goto do_fail_zero;
|
||||
key->poll_hotkey.poll_result =
|
||||
(union acpi_object *)kmalloc(sizeof(union acpi_object), GFP_KERNEL);
|
||||
kmalloc(sizeof(union acpi_object), GFP_KERNEL);
|
||||
if (!key->poll_hotkey.poll_result)
|
||||
goto do_fail_zero;
|
||||
return AE_OK;
|
||||
|
||||
@@ -309,18 +309,16 @@ static int acpi_ec_hc_add(struct acpi_device *device)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ec_hc = kmalloc(sizeof(struct acpi_ec_hc), GFP_KERNEL);
|
||||
ec_hc = kzalloc(sizeof(struct acpi_ec_hc), GFP_KERNEL);
|
||||
if (!ec_hc) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(ec_hc, 0, sizeof(struct acpi_ec_hc));
|
||||
|
||||
smbus = kmalloc(sizeof(struct acpi_ec_smbus), GFP_KERNEL);
|
||||
smbus = kzalloc(sizeof(struct acpi_ec_smbus), GFP_KERNEL);
|
||||
if (!smbus) {
|
||||
kfree(ec_hc);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(smbus, 0, sizeof(struct acpi_ec_smbus));
|
||||
|
||||
ec_hc->handle = device->handle;
|
||||
strcpy(acpi_device_name(device), ACPI_EC_HC_DEVICE_NAME);
|
||||
@@ -393,7 +391,7 @@ static void __exit acpi_ec_hc_exit(void)
|
||||
|
||||
struct acpi_ec_hc *acpi_get_ec_hc(struct acpi_device *device)
|
||||
{
|
||||
return ((struct acpi_ec_hc *)acpi_driver_data(device->parent));
|
||||
return acpi_driver_data(device->parent);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(acpi_get_ec_hc);
|
||||
|
||||
+897
-164
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user