Commit 6b410160 authored by Linus Torvalds's avatar Linus Torvalds

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: (39 commits)
  ACPI: EC: Workaround for optimized controllers (version 3)
  ACPI: EC: use printk_ratelimit(), add some DEBUG mode messages
  Revert "ACPI: EC: Workaround for optimized controllers"
  ACPI: fix two IRQ8 issues in IOAPIC mode
  ACPI: Add missing spaces to printk format
  cpuidle: fix HP nx6125 regression
  cpuidle: add sched_clock_idle_[sleep|wakeup]_event() hooks
  cpuidle: fix C3 for no bus-master control case
  ACPI: thinkpad-acpi: fix oops when a module parameter has no value
  Revert "Fix very high interrupt rate for IRQ8 (rtc) unless pnpacpi=off"
  ACPI: EC: Don't init EC early if it has no _INI
  Revert "acpi: make ACPI_PROCFS default to y"
  Revert "ACPI: add documentation for deprecated /proc/acpi/battery in ACPI_PROCFS"
  ACPI: Split out control for /proc/acpi entries from battery, ac, and sbs.
  ACPI: Video: Increase buffer size for writes to brightness proc file.
  ACPI: EC: Workaround for optimized controllers
  ACPI: SBS: Fix retval warning
  ACPI: Enable MSR (FixedHW) support for T-States
  ACPI: Get throttling info from BIOS only after evaluating _PDC
  ACPI: Use _TSS for throttling control, when present. Add error checks.
  ...
parents 9ccc2362 a3f095ad
ThinkPad ACPI Extras Driver ThinkPad ACPI Extras Driver
Version 0.16 Version 0.17
August 2nd, 2007 October 04th, 2007
Borislav Deianov <borislav@users.sf.net> Borislav Deianov <borislav@users.sf.net>
Henrique de Moraes Holschuh <hmh@hmh.eng.br> Henrique de Moraes Holschuh <hmh@hmh.eng.br>
...@@ -923,19 +923,34 @@ sysfs backlight device "thinkpad_screen" ...@@ -923,19 +923,34 @@ sysfs backlight device "thinkpad_screen"
This feature allows software control of the LCD brightness on ThinkPad This feature allows software control of the LCD brightness on ThinkPad
models which don't have a hardware brightness slider. models which don't have a hardware brightness slider.
It has some limitations: the LCD backlight cannot be actually turned on or off It has some limitations: the LCD backlight cannot be actually turned on or
by this interface, and in many ThinkPad models, the "dim while on battery" off by this interface, and in many ThinkPad models, the "dim while on
functionality will be enabled by the BIOS when this interface is used, and battery" functionality will be enabled by the BIOS when this interface is
cannot be controlled. used, and cannot be controlled.
The backlight control has eight levels, ranging from 0 to 7. Some of the On IBM (and some of the earlier Lenovo) ThinkPads, the backlight control
levels may not be distinct. has eight brightness levels, ranging from 0 to 7. Some of the levels
may not be distinct. Later Lenovo models that implement the ACPI
There are two interfaces to the firmware for brightness control, EC and CMOS. display backlight brightness control methods have 16 levels, ranging
To select which one should be used, use the brightness_mode module parameter: from 0 to 15.
brightness_mode=1 selects EC mode, brightness_mode=2 selects CMOS mode,
brightness_mode=3 selects both EC and CMOS. The driver tries to autodetect There are two interfaces to the firmware for direct brightness control,
which interface to use. EC and CMOS. To select which one should be used, use the
brightness_mode module parameter: brightness_mode=1 selects EC mode,
brightness_mode=2 selects CMOS mode, brightness_mode=3 selects both EC
and CMOS. The driver tries to autodetect which interface to use.
When display backlight brightness controls are available through the
standard ACPI interface, it is best to use it instead of this direct
ThinkPad-specific interface. The driver will disable its native
backlight brightness control interface if it detects that the standard
ACPI interface is available in the ThinkPad.
The brightness_enable module parameter can be used to control whether
the LCD brightness control feature will be enabled when available.
brightness_enable=0 forces it to be disabled. brightness_enable=1
forces it to be enabled when available, even if the standard ACPI
interface is also available.
Procfs notes: Procfs notes:
...@@ -947,11 +962,11 @@ Procfs notes: ...@@ -947,11 +962,11 @@ Procfs notes:
Sysfs notes: Sysfs notes:
The interface is implemented through the backlight sysfs class, which is poorly The interface is implemented through the backlight sysfs class, which is
documented at this time. poorly documented at this time.
Locate the thinkpad_screen device under /sys/class/backlight, and inside it Locate the thinkpad_screen device under /sys/class/backlight, and inside
there will be the following attributes: it there will be the following attributes:
max_brightness: max_brightness:
Reads the maximum brightness the hardware can be set to. Reads the maximum brightness the hardware can be set to.
...@@ -961,17 +976,19 @@ there will be the following attributes: ...@@ -961,17 +976,19 @@ there will be the following attributes:
Reads what brightness the screen is set to at this instant. Reads what brightness the screen is set to at this instant.
brightness: brightness:
Writes request the driver to change brightness to the given Writes request the driver to change brightness to the
value. Reads will tell you what brightness the driver is trying given value. Reads will tell you what brightness the
to set the display to when "power" is set to zero and the display driver is trying to set the display to when "power" is set
has not been dimmed by a kernel power management event. to zero and the display has not been dimmed by a kernel
power management event.
power: power:
power management mode, where 0 is "display on", and 1 to 3 will power management mode, where 0 is "display on", and 1 to 3
dim the display backlight to brightness level 0 because will dim the display backlight to brightness level 0
thinkpad-acpi cannot really turn the backlight off. Kernel because thinkpad-acpi cannot really turn the backlight
power management events can temporarily increase the current off. Kernel power management events can temporarily
power management level, i.e. they can dim the display. increase the current power management level, i.e. they can
dim the display.
Volume control -- /proc/acpi/ibm/volume Volume control -- /proc/acpi/ibm/volume
......
...@@ -49,6 +49,9 @@ static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c) ...@@ -49,6 +49,9 @@ static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c)
if (cpu_has(c, X86_FEATURE_EST)) if (cpu_has(c, X86_FEATURE_EST))
buf[2] |= ACPI_PDC_EST_CAPABILITY_SWSMP; buf[2] |= ACPI_PDC_EST_CAPABILITY_SWSMP;
if (cpu_has(c, X86_FEATURE_ACPI))
buf[2] |= ACPI_PDC_T_FFH;
obj->type = ACPI_TYPE_BUFFER; obj->type = ACPI_TYPE_BUFFER;
obj->buffer.length = 12; obj->buffer.length = 12;
obj->buffer.pointer = (u8 *) buf; obj->buffer.pointer = (u8 *) buf;
......
...@@ -115,6 +115,3 @@ static int __init acpi_sleep_setup(char *str) ...@@ -115,6 +115,3 @@ static int __init acpi_sleep_setup(char *str)
__setup("acpi_sleep=", acpi_sleep_setup); __setup("acpi_sleep=", acpi_sleep_setup);
void acpi_pci_link_exit(void)
{
}
...@@ -962,7 +962,7 @@ static int EISA_ELCR(unsigned int irq) ...@@ -962,7 +962,7 @@ static int EISA_ELCR(unsigned int irq)
#define default_MCA_trigger(idx) (1) #define default_MCA_trigger(idx) (1)
#define default_MCA_polarity(idx) (0) #define default_MCA_polarity(idx) (0)
static int __init MPBIOS_polarity(int idx) static int MPBIOS_polarity(int idx)
{ {
int bus = mp_irqs[idx].mpc_srcbus; int bus = mp_irqs[idx].mpc_srcbus;
int polarity; int polarity;
...@@ -2830,6 +2830,25 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a ...@@ -2830,6 +2830,25 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int edge_level, int a
return 0; return 0;
} }
int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity)
{
int i;
if (skip_ioapic_setup)
return -1;
for (i = 0; i < mp_irq_entries; i++)
if (mp_irqs[i].mpc_irqtype == mp_INT &&
mp_irqs[i].mpc_srcbusirq == bus_irq)
break;
if (i >= mp_irq_entries)
return -1;
*trigger = irq_trigger(i);
*polarity = irq_polarity(i);
return 0;
}
#endif /* CONFIG_ACPI */ #endif /* CONFIG_ACPI */
static int __init parse_disable_timer_pin_1(char *arg) static int __init parse_disable_timer_pin_1(char *arg)
......
...@@ -546,7 +546,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin) ...@@ -546,7 +546,7 @@ int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
#define default_PCI_trigger(idx) (1) #define default_PCI_trigger(idx) (1)
#define default_PCI_polarity(idx) (1) #define default_PCI_polarity(idx) (1)
static int __init MPBIOS_polarity(int idx) static int MPBIOS_polarity(int idx)
{ {
int bus = mp_irqs[idx].mpc_srcbus; int bus = mp_irqs[idx].mpc_srcbus;
int polarity; int polarity;
...@@ -2222,8 +2222,27 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int p ...@@ -2222,8 +2222,27 @@ int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int p
return 0; return 0;
} }
#endif /* CONFIG_ACPI */
int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity)
{
int i;
if (skip_ioapic_setup)
return -1;
for (i = 0; i < mp_irq_entries; i++)
if (mp_irqs[i].mpc_irqtype == mp_INT &&
mp_irqs[i].mpc_srcbusirq == bus_irq)
break;
if (i >= mp_irq_entries)
return -1;
*trigger = irq_trigger(i);
*polarity = irq_polarity(i);
return 0;
}
#endif /* CONFIG_ACPI */
/* /*
* This function currently is only a helper for the i386 smp boot process where * This function currently is only a helper for the i386 smp boot process where
...@@ -2260,3 +2279,4 @@ void __init setup_ioapic_dest(void) ...@@ -2260,3 +2279,4 @@ void __init setup_ioapic_dest(void)
} }
} }
#endif #endif
...@@ -13,7 +13,7 @@ static int __devinit can_skip_ioresource_align(const struct dmi_system_id *d) ...@@ -13,7 +13,7 @@ static int __devinit can_skip_ioresource_align(const struct dmi_system_id *d)
return 0; return 0;
} }
static struct dmi_system_id acpi_pciprobe_dmi_table[] = { static struct dmi_system_id acpi_pciprobe_dmi_table[] __devinitdata = {
/* /*
* Systems where PCI IO resource ISA alignment can be skipped * Systems where PCI IO resource ISA alignment can be skipped
* when the ISA enable bit in the bridge control is not set * when the ISA enable bit in the bridge control is not set
......
...@@ -50,7 +50,6 @@ config ACPI_SLEEP ...@@ -50,7 +50,6 @@ config ACPI_SLEEP
config ACPI_PROCFS config ACPI_PROCFS
bool "Deprecated /proc/acpi files" bool "Deprecated /proc/acpi files"
depends on PROC_FS depends on PROC_FS
default y
---help--- ---help---
For backwards compatibility, this option allows For backwards compatibility, this option allows
deprecated /proc/acpi/ files to exist, even when deprecated /proc/acpi/ files to exist, even when
...@@ -61,7 +60,6 @@ config ACPI_PROCFS ...@@ -61,7 +60,6 @@ config ACPI_PROCFS
/proc/acpi/info (/sys/modules/acpi/parameters/acpica_version) /proc/acpi/info (/sys/modules/acpi/parameters/acpica_version)
/proc/acpi/dsdt (/sys/firmware/acpi/tables/DSDT) /proc/acpi/dsdt (/sys/firmware/acpi/tables/DSDT)
/proc/acpi/fadt (/sys/firmware/acpi/tables/FACP) /proc/acpi/fadt (/sys/firmware/acpi/tables/FACP)
/proc/acpi/battery (/sys/class/power_supply)
/proc/acpi/debug_layer (/sys/module/acpi/parameters/debug_layer) /proc/acpi/debug_layer (/sys/module/acpi/parameters/debug_layer)
/proc/acpi/debug_level (/sys/module/acpi/parameters/debug_level) /proc/acpi/debug_level (/sys/module/acpi/parameters/debug_level)
...@@ -69,7 +67,21 @@ config ACPI_PROCFS ...@@ -69,7 +67,21 @@ config ACPI_PROCFS
and functions which do not yet exist in /sys. and functions which do not yet exist in /sys.
Say N to delete /proc/acpi/ files that have moved to /sys/ Say N to delete /proc/acpi/ files that have moved to /sys/
config ACPI_PROCFS_POWER
bool "Deprecated power /proc/acpi folders"
depends on PROC_FS
default y
---help---
For backwards compatibility, this option allows
deprecated power /proc/acpi/ folders to exist, even when
they have been replaced by functions in /sys.
The deprecated folders (and their replacements) include:
/proc/acpi/battery/* (/sys/class/power_supply/*)
/proc/acpi/ac_adapter/* (sys/class/power_supply/*)
This option has no effect on /proc/acpi/ folders
and functions, which do not yet exist in /sys
Say N to delete power /proc/acpi/ folders that have moved to /sys/
config ACPI_PROC_EVENT config ACPI_PROC_EVENT
bool "Deprecated /proc/acpi/event support" bool "Deprecated /proc/acpi/event support"
depends on PROC_FS depends on PROC_FS
......
...@@ -58,6 +58,6 @@ obj-$(CONFIG_ACPI_NUMA) += numa.o ...@@ -58,6 +58,6 @@ obj-$(CONFIG_ACPI_NUMA) += numa.o
obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o
obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o
obj-y += cm_sbs.o obj-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o
obj-$(CONFIG_ACPI_SBS) += sbs.o obj-$(CONFIG_ACPI_SBS) += sbs.o
obj-$(CONFIG_ACPI_SBS) += sbshc.o obj-$(CONFIG_ACPI_SBS) += sbshc.o
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/types.h> #include <linux/types.h>
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS_POWER
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#endif #endif
...@@ -51,7 +51,7 @@ MODULE_AUTHOR("Paul Diefenbaugh"); ...@@ -51,7 +51,7 @@ MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION("ACPI AC Adapter Driver"); MODULE_DESCRIPTION("ACPI AC Adapter Driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS_POWER
extern struct proc_dir_entry *acpi_lock_ac_dir(void); extern struct proc_dir_entry *acpi_lock_ac_dir(void);
extern void *acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir); extern void *acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir);
static int acpi_ac_open_fs(struct inode *inode, struct file *file); static int acpi_ac_open_fs(struct inode *inode, struct file *file);
...@@ -86,7 +86,7 @@ struct acpi_ac { ...@@ -86,7 +86,7 @@ struct acpi_ac {
#define to_acpi_ac(x) container_of(x, struct acpi_ac, charger); #define to_acpi_ac(x) container_of(x, struct acpi_ac, charger);
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS_POWER
static const struct file_operations acpi_ac_fops = { static const struct file_operations acpi_ac_fops = {
.open = acpi_ac_open_fs, .open = acpi_ac_open_fs,
.read = seq_read, .read = seq_read,
...@@ -136,7 +136,7 @@ static int acpi_ac_get_state(struct acpi_ac *ac) ...@@ -136,7 +136,7 @@ static int acpi_ac_get_state(struct acpi_ac *ac)
return 0; return 0;
} }
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS_POWER
/* -------------------------------------------------------------------------- /* --------------------------------------------------------------------------
FS Interface (/proc) FS Interface (/proc)
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */
...@@ -275,7 +275,7 @@ static int acpi_ac_add(struct acpi_device *device) ...@@ -275,7 +275,7 @@ static int acpi_ac_add(struct acpi_device *device)
if (result) if (result)
goto end; goto end;
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS_POWER
result = acpi_ac_add_fs(device); result = acpi_ac_add_fs(device);
#endif #endif
if (result) if (result)
...@@ -300,7 +300,7 @@ static int acpi_ac_add(struct acpi_device *device) ...@@ -300,7 +300,7 @@ static int acpi_ac_add(struct acpi_device *device)
end: end:
if (result) { if (result) {
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS_POWER
acpi_ac_remove_fs(device); acpi_ac_remove_fs(device);
#endif #endif
kfree(ac); kfree(ac);
...@@ -339,7 +339,7 @@ static int acpi_ac_remove(struct acpi_device *device, int type) ...@@ -339,7 +339,7 @@ static int acpi_ac_remove(struct acpi_device *device, int type)
ACPI_ALL_NOTIFY, acpi_ac_notify); ACPI_ALL_NOTIFY, acpi_ac_notify);
if (ac->charger.dev) if (ac->charger.dev)
power_supply_unregister(&ac->charger); power_supply_unregister(&ac->charger);
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS_POWER
acpi_ac_remove_fs(device); acpi_ac_remove_fs(device);
#endif #endif
...@@ -355,7 +355,7 @@ static int __init acpi_ac_init(void) ...@@ -355,7 +355,7 @@ static int __init acpi_ac_init(void)
if (acpi_disabled) if (acpi_disabled)
return -ENODEV; return -ENODEV;
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS_POWER
acpi_ac_dir = acpi_lock_ac_dir(); acpi_ac_dir = acpi_lock_ac_dir();
if (!acpi_ac_dir) if (!acpi_ac_dir)
return -ENODEV; return -ENODEV;
...@@ -363,7 +363,7 @@ static int __init acpi_ac_init(void) ...@@ -363,7 +363,7 @@ static int __init acpi_ac_init(void)
result = acpi_bus_register_driver(&acpi_ac_driver); result = acpi_bus_register_driver(&acpi_ac_driver);
if (result < 0) { if (result < 0) {
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS_POWER
acpi_unlock_ac_dir(acpi_ac_dir); acpi_unlock_ac_dir(acpi_ac_dir);
#endif #endif
return -ENODEV; return -ENODEV;
...@@ -377,7 +377,7 @@ static void __exit acpi_ac_exit(void) ...@@ -377,7 +377,7 @@ static void __exit acpi_ac_exit(void)
acpi_bus_unregister_driver(&acpi_ac_driver); acpi_bus_unregister_driver(&acpi_ac_driver);
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS_POWER
acpi_unlock_ac_dir(acpi_ac_dir); acpi_unlock_ac_dir(acpi_ac_dir);
#endif #endif
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS_POWER
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -63,7 +63,7 @@ static unsigned int cache_time = 1000; ...@@ -63,7 +63,7 @@ static unsigned int cache_time = 1000;
module_param(cache_time, uint, 0644); module_param(cache_time, uint, 0644);
MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS_POWER
extern struct proc_dir_entry *acpi_lock_battery_dir(void); extern struct proc_dir_entry *acpi_lock_battery_dir(void);
extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
...@@ -153,6 +153,8 @@ static int acpi_battery_get_property(struct power_supply *psy, ...@@ -153,6 +153,8 @@ static int acpi_battery_get_property(struct power_supply *psy,
val->intval = POWER_SUPPLY_STATUS_CHARGING; val->intval = POWER_SUPPLY_STATUS_CHARGING;
else if (battery->state == 0) else if (battery->state == 0)
val->intval = POWER_SUPPLY_STATUS_FULL; val->intval = POWER_SUPPLY_STATUS_FULL;
else
val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
break; break;
case POWER_SUPPLY_PROP_PRESENT: case POWER_SUPPLY_PROP_PRESENT:
val->intval = acpi_battery_present(battery); val->intval = acpi_battery_present(battery);
...@@ -221,7 +223,7 @@ static enum power_supply_property energy_battery_props[] = { ...@@ -221,7 +223,7 @@ static enum power_supply_property energy_battery_props[] = {
POWER_SUPPLY_PROP_MANUFACTURER, POWER_SUPPLY_PROP_MANUFACTURER,
}; };
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS_POWER
inline char *acpi_battery_units(struct acpi_battery *battery) inline char *acpi_battery_units(struct acpi_battery *battery)
{ {
return (battery->power_unit)?"mA":"mW"; return (battery->power_unit)?"mA":"mW";
...@@ -479,7 +481,7 @@ static int acpi_battery_update(struct acpi_battery *battery) ...@@ -479,7 +481,7 @@ static int acpi_battery_update(struct acpi_battery *battery)
FS Interface (/proc) FS Interface (/proc)
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS_POWER
static struct proc_dir_entry *acpi_battery_dir; static struct proc_dir_entry *acpi_battery_dir;
static int acpi_battery_print_info(struct seq_file *seq, int result) static int acpi_battery_print_info(struct seq_file *seq, int result)
...@@ -786,7 +788,7 @@ static int acpi_battery_add(struct acpi_device *device) ...@@ -786,7 +788,7 @@ static int acpi_battery_add(struct acpi_device *device)
acpi_driver_data(device) = battery; acpi_driver_data(device) = battery;
mutex_init(&battery->lock); mutex_init(&battery->lock);
acpi_battery_update(battery); acpi_battery_update(battery);
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS_POWER
result = acpi_battery_add_fs(device); result = acpi_battery_add_fs(device);
if (result) if (result)
goto end; goto end;
...@@ -804,7 +806,7 @@ static int acpi_battery_add(struct acpi_device *device) ...@@ -804,7 +806,7 @@ static int acpi_battery_add(struct acpi_device *device)
device->status.battery_present ? "present" : "absent"); device->status.battery_present ? "present" : "absent");
end: end:
if (result) { if (result) {
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS_POWER
acpi_battery_remove_fs(device); acpi_battery_remove_fs(device);
#endif #endif
kfree(battery); kfree(battery);
...@@ -823,7 +825,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type) ...@@ -823,7 +825,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
status = acpi_remove_notify_handler(device->handle, status = acpi_remove_notify_handler(device->handle,
ACPI_ALL_NOTIFY, ACPI_ALL_NOTIFY,
acpi_battery_notify); acpi_battery_notify);
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS_POWER
acpi_battery_remove_fs(device); acpi_battery_remove_fs(device);
#endif #endif
sysfs_remove_battery(battery); sysfs_remove_battery(battery);
...@@ -859,13 +861,13 @@ static int __init acpi_battery_init(void) ...@@ -859,13 +861,13 @@ static int __init acpi_battery_init(void)
{ {
if (acpi_disabled) if (acpi_disabled)
return -ENODEV; return -ENODEV;
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS_POWER
acpi_battery_dir = acpi_lock_battery_dir(); acpi_battery_dir = acpi_lock_battery_dir();
if (!acpi_battery_dir) if (!acpi_battery_dir)
return -ENODEV; return -ENODEV;
#endif #endif
if (acpi_bus_register_driver(&acpi_battery_driver) < 0) { if (acpi_bus_register_driver(&acpi_battery_driver) < 0) {
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS_POWER
acpi_unlock_battery_dir(acpi_battery_dir); acpi_unlock_battery_dir(acpi_battery_dir);
#endif #endif
return -ENODEV; return -ENODEV;
...@@ -876,7 +878,7 @@ static int __init acpi_battery_init(void) ...@@ -876,7 +878,7 @@ static int __init acpi_battery_init(void)
static void __exit acpi_battery_exit(void) static void __exit acpi_battery_exit(void)
{ {
acpi_bus_unregister_driver(&acpi_battery_driver); acpi_bus_unregister_driver(&acpi_battery_driver);
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS_POWER
acpi_unlock_battery_dir(acpi_battery_dir); acpi_unlock_battery_dir(acpi_battery_dir);
#endif #endif
} }
......
...@@ -47,6 +47,9 @@ ...@@ -47,6 +47,9 @@
#undef PREFIX #undef PREFIX
#define PREFIX "ACPI: EC: " #define PREFIX "ACPI: EC: "
/* Uncomment next line to get verbose print outs*/
/* #define DEBUG */
/* EC status register */ /* EC status register */
#define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ #define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */
#define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ #define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */
...@@ -75,7 +78,10 @@ enum { ...@@ -75,7 +78,10 @@ enum {
EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */ EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */
EC_FLAGS_QUERY_PENDING, /* Query is pending */ EC_FLAGS_QUERY_PENDING, /* Query is pending */
EC_FLAGS_GPE_MODE, /* Expect GPE to be sent for status change */ EC_FLAGS_GPE_MODE, /* Expect GPE to be sent for status change */
EC_FLAGS_ONLY_IBF_GPE, /* Expect GPE only for IBF = 0 event */ EC_FLAGS_NO_ADDRESS_GPE, /* Expect GPE only for non-address event */
EC_FLAGS_ADDRESS, /* Address is being written */
EC_FLAGS_NO_WDATA_GPE, /* Don't expect WDATA GPE event */
EC_FLAGS_WDATA, /* Data is being written */
}; };
static int acpi_ec_remove(struct acpi_device *device, int type); static int acpi_ec_remove(struct acpi_device *device, int type);
...@@ -131,21 +137,27 @@ static struct acpi_ec { ...@@ -131,21 +137,27 @@ static struct acpi_ec {
static inline u8 acpi_ec_read_status(struct acpi_ec *ec) static inline u8 acpi_ec_read_status(struct acpi_ec *ec)
{ {
return inb(ec->command_addr); u8 x = inb(ec->command_addr);
pr_debug(PREFIX "---> status = 0x%2x\n", x);
return x;
} }
static inline u8 acpi_ec_read_data(struct acpi_ec *ec) static inline u8 acpi_ec_read_data(struct acpi_ec *ec)
{ {
u8 x = inb(ec->data_addr);
pr_debug(PREFIX "---> data = 0x%2x\n", x);
return inb(ec->data_addr); return inb(ec->data_addr);
} }
static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command) static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command)
{ {
pr_debug(PREFIX "<--- command = 0x%2x\n", command);
outb(command, ec->command_addr); outb(command, ec->command_addr);
} }
static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data) static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data)
{ {
pr_debug(PREFIX "<--- data = 0x%2x\n", data);
outb(data, ec->data_addr); outb(data, ec->data_addr);
} }
...@@ -166,38 +178,54 @@ static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event) ...@@ -166,38 +178,54 @@ static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event)
static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll)
{ {
int ret = 0;
if (unlikely(test_bit(EC_FLAGS_ADDRESS, &ec->flags) &&
test_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags)))
force_poll = 1;
if (unlikely(test_bit(EC_FLAGS_WDATA, &ec->flags) &&
test_bit(EC_FLAGS_NO_WDATA_GPE, &ec->flags)))
force_poll = 1;
if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) && if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) &&
likely(!force_poll)) { likely(!force_poll)) {
if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event), if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event),
msecs_to_jiffies(ACPI_EC_DELAY))) msecs_to_jiffies(ACPI_EC_DELAY)))
return 0; goto end;
clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
if (acpi_ec_check_status(ec, event)) { if (acpi_ec_check_status(ec, event)) {
if (event == ACPI_EC_EVENT_OBF_1) { if (test_bit(EC_FLAGS_ADDRESS, &ec->flags)) {
/* miss OBF = 1 GPE, don't expect it anymore */ /* miss address GPE, don't expect it anymore */
printk(KERN_INFO PREFIX "missing OBF_1 confirmation," pr_info(PREFIX "missing address confirmation, "
"switching to degraded mode.\n"); "don't expect it any longer.\n");
set_bit(EC_FLAGS_ONLY_IBF_GPE, &ec->flags); set_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags);
} else if (test_bit(EC_FLAGS_WDATA, &ec->flags)) {
/* miss write data GPE, don't expect it */
pr_info(PREFIX "missing write data confirmation, "
"don't expect it any longer.\n");
set_bit(EC_FLAGS_NO_WDATA_GPE, &ec->flags);
} else { } else {
/* missing GPEs, switch back to poll mode */ /* missing GPEs, switch back to poll mode */
printk(KERN_INFO PREFIX "missing IBF_1 confirmations," if (printk_ratelimit())
"switch off interrupt mode.\n"); pr_info(PREFIX "missing confirmations, "
"switch off interrupt mode.\n");
clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
} }
return 0; goto end;
} }
} else { } else {
unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
while (time_before(jiffies, delay)) { while (time_before(jiffies, delay)) {
if (acpi_ec_check_status(ec, event)) if (acpi_ec_check_status(ec, event))
return 0; goto end;
} }
} }
printk(KERN_ERR PREFIX "acpi_ec_wait timeout," pr_err(PREFIX "acpi_ec_wait timeout,"
" status = %d, expect_event = %d\n", " status = %d, expect_event = %d\n",
acpi_ec_read_status(ec), event); acpi_ec_read_status(ec), event);
return -ETIME; ret = -ETIME;
end:
clear_bit(EC_FLAGS_ADDRESS, &ec->flags);
return ret;
} }
static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
...@@ -208,22 +236,26 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, ...@@ -208,22 +236,26 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
int result = 0; int result = 0;
set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); set_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
acpi_ec_write_cmd(ec, command); acpi_ec_write_cmd(ec, command);
pr_debug(PREFIX "transaction start\n");
for (; wdata_len > 0; --wdata_len) { for (; wdata_len > 0; --wdata_len) {
result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll);
if (result) { if (result) {
printk(KERN_ERR PREFIX pr_err(PREFIX
"write_cmd timeout, command = %d\n", command); "write_cmd timeout, command = %d\n", command);
goto end; goto end;
} }
/* mark the address byte written to EC */
if (rdata_len + wdata_len > 1)
set_bit(EC_FLAGS_ADDRESS, &ec->flags);
set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); set_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
acpi_ec_write_data(ec, *(wdata++)); acpi_ec_write_data(ec, *(wdata++));
} }
if (!rdata_len) { if (!rdata_len) {
set_bit(EC_FLAGS_WDATA, &ec->flags);
result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll);
if (result) { if (result) {
printk(KERN_ERR PREFIX pr_err(PREFIX
"finish-write timeout, command = %d\n", command); "finish-write timeout, command = %d\n", command);
goto end; goto end;
} }
...@@ -231,12 +263,9 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, ...@@ -231,12 +263,9 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
for (; rdata_len > 0; --rdata_len) { for (; rdata_len > 0; --rdata_len) {
if (test_bit(EC_FLAGS_ONLY_IBF_GPE, &ec->flags))
force_poll = 1;
result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, force_poll); result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, force_poll);
if (result) { if (result) {
printk(KERN_ERR PREFIX "read timeout, command = %d\n", pr_err(PREFIX "read timeout, command = %d\n", command);
command);
goto end; goto end;
} }
/* Don't expect GPE after last read */ /* Don't expect GPE after last read */
...@@ -245,6 +274,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, ...@@ -245,6 +274,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
*(rdata++) = acpi_ec_read_data(ec); *(rdata++) = acpi_ec_read_data(ec);
} }
end: end:
pr_debug(PREFIX "transaction end\n");
return result; return result;
} }
...@@ -273,8 +303,8 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, ...@@ -273,8 +303,8 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0); status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0);
if (status) { if (status) {
printk(KERN_ERR PREFIX pr_err(PREFIX "input buffer is not empty, "
"input buffer is not empty, aborting transaction\n"); "aborting transaction\n");
goto end; goto end;
} }
...@@ -488,6 +518,7 @@ static u32 acpi_ec_gpe_handler(void *data) ...@@ -488,6 +518,7 @@ static u32 acpi_ec_gpe_handler(void *data)
acpi_status status = AE_OK; acpi_status status = AE_OK;
struct acpi_ec *ec = data; struct acpi_ec *ec = data;
pr_debug(PREFIX "~~~> interrupt\n");
clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags))
wake_up(&ec->wait); wake_up(&ec->wait);
...@@ -498,8 +529,9 @@ static u32 acpi_ec_gpe_handler(void *data) ...@@ -498,8 +529,9 @@ static u32 acpi_ec_gpe_handler(void *data)
acpi_ec_gpe_query, ec); acpi_ec_gpe_query, ec);
} else if (unlikely(!test_bit(EC_FLAGS_GPE_MODE, &ec->flags))) { } else if (unlikely(!test_bit(EC_FLAGS_GPE_MODE, &ec->flags))) {
/* this is non-query, must be confirmation */ /* this is non-query, must be confirmation */
printk(KERN_INFO PREFIX "non-query interrupt received," if (printk_ratelimit())
" switching to interrupt mode\n"); pr_info(PREFIX "non-query interrupt received,"
" switching to interrupt mode\n");
set_bit(EC_FLAGS_GPE_MODE, &ec->flags); set_bit(EC_FLAGS_GPE_MODE, &ec->flags);
} }
...@@ -701,10 +733,10 @@ static void ec_remove_handlers(struct acpi_ec *ec) ...@@ -701,10 +733,10 @@ static void ec_remove_handlers(struct acpi_ec *ec)
{ {
if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle, if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle,
ACPI_ADR_SPACE_EC, &acpi_ec_space_handler))) ACPI_ADR_SPACE_EC, &acpi_ec_space_handler)))
printk(KERN_ERR PREFIX "failed to remove space handler\n"); pr_err(PREFIX "failed to remove space handler\n");
if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe, if (ACPI_FAILURE(acpi_remove_gpe_handler(NULL, ec->gpe,
&acpi_ec_gpe_handler))) &acpi_ec_gpe_handler)))
printk(KERN_ERR PREFIX "failed to remove gpe handler\n"); pr_err(PREFIX "failed to remove gpe handler\n");
ec->handlers_installed = 0; ec->handlers_installed = 0;
} }
...@@ -747,9 +779,9 @@ static int acpi_ec_add(struct acpi_device *device) ...@@ -747,9 +779,9 @@ static int acpi_ec_add(struct acpi_device *device)
first_ec = ec; first_ec = ec;
acpi_driver_data(device) = ec; acpi_driver_data(device) = ec;
acpi_ec_add_fs(device); acpi_ec_add_fs(device);
printk(KERN_INFO PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n", pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
ec->gpe, ec->command_addr, ec->data_addr); ec->gpe, ec->command_addr, ec->data_addr);
printk(KERN_INFO PREFIX "driver started in %s mode\n", pr_info(PREFIX "driver started in %s mode\n",
(test_bit(EC_FLAGS_GPE_MODE, &ec->flags))?"interrupt":"poll"); (test_bit(EC_FLAGS_GPE_MODE, &ec->flags))?"interrupt":"poll");
return 0; return 0;
} }
...@@ -875,18 +907,26 @@ int __init acpi_ec_ecdt_probe(void) ...@@ -875,18 +907,26 @@ int __init acpi_ec_ecdt_probe(void)
status = acpi_get_table(ACPI_SIG_ECDT, 1, status = acpi_get_table(ACPI_SIG_ECDT, 1,
(struct acpi_table_header **)&ecdt_ptr); (struct acpi_table_header **)&ecdt_ptr);
if (ACPI_SUCCESS(status)) { if (ACPI_SUCCESS(status)) {
printk(KERN_INFO PREFIX "EC description table is found, configuring boot EC\n"); pr_info(PREFIX "EC description table is found, configuring boot EC\n");
boot_ec->command_addr = ecdt_ptr->control.address; boot_ec->command_addr = ecdt_ptr->control.address;
boot_ec->data_addr = ecdt_ptr->data.address; boot_ec->data_addr = ecdt_ptr->data.address;
boot_ec->gpe = ecdt_ptr->gpe; boot_ec->gpe = ecdt_ptr->gpe;
boot_ec->handle = ACPI_ROOT_OBJECT; boot_ec->handle = ACPI_ROOT_OBJECT;
} else { } else {
/* This workaround is needed only on some broken machines,
* which require early EC, but fail to provide ECDT */
acpi_handle x;
printk(KERN_DEBUG PREFIX "Look up EC in DSDT\n"); printk(KERN_DEBUG PREFIX "Look up EC in DSDT\n");
status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device, status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device,
boot_ec, NULL); boot_ec, NULL);
/* Check that acpi_get_devices actually find something */ /* Check that acpi_get_devices actually find something */
if (ACPI_FAILURE(status) || !boot_ec->handle) if (ACPI_FAILURE(status) || !boot_ec->handle)
goto error; goto error;
/* We really need to limit this workaround, the only ASUS,
* which needs it, has fake EC._INI method, so use it as flag.
*/
if (ACPI_FAILURE(acpi_get_handle(boot_ec->handle, "_INI", &x)))
goto error;
} }
ret = ec_install_handlers(boot_ec); ret = ec_install_handlers(boot_ec);
......
...@@ -387,17 +387,14 @@ acpi_status acpi_os_read_port(acpi_io_address port, u32 * value, u32 width) ...@@ -387,17 +387,14 @@ acpi_status acpi_os_read_port(acpi_io_address port, u32 * value, u32 width)
if (!value) if (!value)
value = &dummy; value = &dummy;
switch (width) { *value = 0;
case 8: if (width <= 8) {
*(u8 *) value = inb(port); *(u8 *) value = inb(port);
break; } else if (width <= 16) {
case 16:
*(u16 *) value = inw(port); *(u16 *) value = inw(port);
break; } else if (width <= 32) {
case 32:
*(u32 *) value = inl(port); *(u32 *) value = inl(port);
break; } else {
default:
BUG(); BUG();
} }
...@@ -408,17 +405,13 @@ EXPORT_SYMBOL(acpi_os_read_port); ...@@ -408,17 +405,13 @@ EXPORT_SYMBOL(acpi_os_read_port);
acpi_status acpi_os_write_port(acpi_io_address port, u32 value, u32 width) acpi_status acpi_os_write_port(acpi_io_address port, u32 value, u32 width)
{ {
switch (width) { if (width <= 8) {
case 8:
outb(value, port); outb(value, port);
break; } else if (width <= 16) {
case 16:
outw(value, port); outw(value, port);
break; } else if (width <= 32) {
case 32:
outl(value, port); outl(value, port);
break; } else {
default:
BUG(); BUG();
} }
......
...@@ -612,12 +612,6 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid) ...@@ -612,12 +612,6 @@ static int acpi_processor_get_info(struct acpi_processor *pr, unsigned has_uid)
request_region(pr->throttling.address, 6, "ACPI CPU throttle"); request_region(pr->throttling.address, 6, "ACPI CPU throttle");
} }
#ifdef CONFIG_CPU_FREQ
acpi_processor_ppc_has_changed(pr);
#endif
acpi_processor_get_throttling_info(pr);
acpi_processor_get_limit_info(pr);
return 0; return 0;
} }
...@@ -647,7 +641,7 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device) ...@@ -647,7 +641,7 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device)
*/ */
if (processor_device_array[pr->id] != NULL && if (processor_device_array[pr->id] != NULL &&
processor_device_array[pr->id] != device) { processor_device_array[pr->id] != device) {
printk(KERN_WARNING "BIOS reported wrong ACPI id" printk(KERN_WARNING "BIOS reported wrong ACPI id "
"for the processor\n"); "for the processor\n");
return -ENODEV; return -ENODEV;
} }
...@@ -665,6 +659,12 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device) ...@@ -665,6 +659,12 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device)
/* _PDC call should be done before doing anything else (if reqd.). */ /* _PDC call should be done before doing anything else (if reqd.). */
arch_acpi_processor_init_pdc(pr); arch_acpi_processor_init_pdc(pr);
acpi_processor_set_pdc(pr); acpi_processor_set_pdc(pr);
#ifdef CONFIG_CPU_FREQ
acpi_processor_ppc_has_changed(pr);
#endif
acpi_processor_get_throttling_info(pr);
acpi_processor_get_limit_info(pr);
acpi_processor_power_init(pr, device); acpi_processor_power_init(pr, device);
...@@ -684,7 +684,7 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data) ...@@ -684,7 +684,7 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data)
{ {
struct acpi_processor *pr = data; struct acpi_processor *pr = data;
struct acpi_device *device = NULL; struct acpi_device *device = NULL;
int saved;
if (!pr) if (!pr)
return; return;
...@@ -694,7 +694,10 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data) ...@@ -694,7 +694,10 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data)
switch (event) { switch (event) {
case ACPI_PROCESSOR_NOTIFY_PERFORMANCE: case ACPI_PROCESSOR_NOTIFY_PERFORMANCE:
saved = pr->performance_platform_limit;
acpi_processor_ppc_has_changed(pr); acpi_processor_ppc_has_changed(pr);
if (saved == pr->performance_platform_limit)
break;
acpi_bus_generate_proc_event(device, event, acpi_bus_generate_proc_event(device, event,
pr->performance_platform_limit); pr->performance_platform_limit);
acpi_bus_generate_netlink_event(device->pnp.device_class, acpi_bus_generate_netlink_event(device->pnp.device_class,
......
...@@ -197,6 +197,19 @@ static inline u32 ticks_elapsed_in_us(u32 t1, u32 t2) ...@@ -197,6 +197,19 @@ static inline u32 ticks_elapsed_in_us(u32 t1, u32 t2)
return PM_TIMER_TICKS_TO_US((0xFFFFFFFF - t1) + t2); return PM_TIMER_TICKS_TO_US((0xFFFFFFFF - t1) + t2);
} }
static void acpi_safe_halt(void)
{
current_thread_info()->status &= ~TS_POLLING;
/*
* TS_POLLING-cleared state must be visible before we
* test NEED_RESCHED:
*/
smp_mb();
if (!need_resched())
safe_halt();
current_thread_info()->status |= TS_POLLING;
}
#ifndef CONFIG_CPU_IDLE #ifndef CONFIG_CPU_IDLE
static void static void
...@@ -239,19 +252,6 @@ acpi_processor_power_activate(struct acpi_processor *pr, ...@@ -239,19 +252,6 @@ acpi_processor_power_activate(struct acpi_processor *pr,
return; return;
} }
static void acpi_safe_halt(void)
{
current_thread_info()->status &= ~TS_POLLING;
/*
* TS_POLLING-cleared state must be visible before we
* test NEED_RESCHED:
*/
smp_mb();
if (!need_resched())
safe_halt();
current_thread_info()->status |= TS_POLLING;
}
static atomic_t c3_cpu_count; static atomic_t c3_cpu_count;
/* Common C-state entry for C2, C3, .. */ /* Common C-state entry for C2, C3, .. */
...@@ -1373,15 +1373,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, ...@@ -1373,15 +1373,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
if (pr->flags.bm_check) if (pr->flags.bm_check)
acpi_idle_update_bm_rld(pr, cx); acpi_idle_update_bm_rld(pr, cx);
current_thread_info()->status &= ~TS_POLLING; acpi_safe_halt();
/*
* TS_POLLING-cleared state must be visible before we test
* NEED_RESCHED:
*/
smp_mb();
if (!need_resched())
safe_halt();
current_thread_info()->status |= TS_POLLING;
cx->usage++; cx->usage++;
...@@ -1399,6 +1391,8 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, ...@@ -1399,6 +1391,8 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
struct acpi_processor *pr; struct acpi_processor *pr;
struct acpi_processor_cx *cx = cpuidle_get_statedata(state); struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
u32 t1, t2; u32 t1, t2;
int sleep_ticks = 0;
pr = processors[smp_processor_id()]; pr = processors[smp_processor_id()];
if (unlikely(!pr)) if (unlikely(!pr))
...@@ -1428,6 +1422,8 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, ...@@ -1428,6 +1422,8 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
ACPI_FLUSH_CPU_CACHE(); ACPI_FLUSH_CPU_CACHE();
t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
/* Tell the scheduler that we are going deep-idle: */
sched_clock_idle_sleep_event();
acpi_state_timer_broadcast(pr, cx, 1); acpi_state_timer_broadcast(pr, cx, 1);
acpi_idle_do_entry(cx); acpi_idle_do_entry(cx);
t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
...@@ -1436,6 +1432,10 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, ...@@ -1436,6 +1432,10 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
/* TSC could halt in idle, so notify users */ /* TSC could halt in idle, so notify users */
mark_tsc_unstable("TSC halts in idle");; mark_tsc_unstable("TSC halts in idle");;
#endif #endif
sleep_ticks = ticks_elapsed(t1, t2);
/* Tell the scheduler how much we idled: */
sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS);
local_irq_enable(); local_irq_enable();
current_thread_info()->status |= TS_POLLING; current_thread_info()->status |= TS_POLLING;
...@@ -1443,7 +1443,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, ...@@ -1443,7 +1443,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
cx->usage++; cx->usage++;
acpi_state_timer_broadcast(pr, cx, 0); acpi_state_timer_broadcast(pr, cx, 0);
cx->time += ticks_elapsed(t1, t2); cx->time += sleep_ticks;
return ticks_elapsed_in_us(t1, t2); return ticks_elapsed_in_us(t1, t2);
} }
...@@ -1463,6 +1463,8 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, ...@@ -1463,6 +1463,8 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
struct acpi_processor *pr; struct acpi_processor *pr;
struct acpi_processor_cx *cx = cpuidle_get_statedata(state); struct acpi_processor_cx *cx = cpuidle_get_statedata(state);
u32 t1, t2; u32 t1, t2;
int sleep_ticks = 0;
pr = processors[smp_processor_id()]; pr = processors[smp_processor_id()];
if (unlikely(!pr)) if (unlikely(!pr))
...@@ -1471,6 +1473,15 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, ...@@ -1471,6 +1473,15 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
if (acpi_idle_suspend) if (acpi_idle_suspend)
return(acpi_idle_enter_c1(dev, state)); return(acpi_idle_enter_c1(dev, state));
if (acpi_idle_bm_check()) {
if (dev->safe_state) {
return dev->safe_state->enter(dev, dev->safe_state);
} else {
acpi_safe_halt();
return 0;
}
}
local_irq_disable(); local_irq_disable();
current_thread_info()->status &= ~TS_POLLING; current_thread_info()->status &= ~TS_POLLING;
/* /*
...@@ -1485,38 +1496,45 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, ...@@ -1485,38 +1496,45 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
return 0; return 0;
} }
/* Tell the scheduler that we are going deep-idle: */
sched_clock_idle_sleep_event();
/* /*
* Must be done before busmaster disable as we might need to * Must be done before busmaster disable as we might need to
* access HPET ! * access HPET !
*/ */
acpi_state_timer_broadcast(pr, cx, 1); acpi_state_timer_broadcast(pr, cx, 1);
if (acpi_idle_bm_check()) { acpi_idle_update_bm_rld(pr, cx);
cx = pr->power.bm_state;
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);
} else {
acpi_idle_update_bm_rld(pr, cx);
/*
* disable bus master
* bm_check implies we need ARB_DIS
* !bm_check implies we need cache flush
* bm_control implies whether we can do ARB_DIS
*
* That leaves a case where bm_check is set and bm_control is
* not set. In that case we cannot do much, we enter C3
* without doing anything.
*/
if (pr->flags.bm_check && pr->flags.bm_control) {
spin_lock(&c3_lock); spin_lock(&c3_lock);
c3_cpu_count++; c3_cpu_count++;
/* Disable bus master arbitration when all CPUs are in C3 */ /* Disable bus master arbitration when all CPUs are in C3 */
if (c3_cpu_count == num_online_cpus()) if (c3_cpu_count == num_online_cpus())
acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1); acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1);
spin_unlock(&c3_lock); spin_unlock(&c3_lock);
} else if (!pr->flags.bm_check) {
ACPI_FLUSH_CPU_CACHE();
}
t1 = inl(acpi_gbl_FADT.xpm_timer_block.address); t1 = inl(acpi_gbl_FADT.xpm_timer_block.address);
acpi_idle_do_entry(cx); acpi_idle_do_entry(cx);
t2 = inl(acpi_gbl_FADT.xpm_timer_block.address); t2 = inl(acpi_gbl_FADT.xpm_timer_block.address);
/* Re-enable bus master arbitration */
if (pr->flags.bm_check && pr->flags.bm_control) {
spin_lock(&c3_lock); spin_lock(&c3_lock);
/* Re-enable bus master arbitration */ acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0);
if (c3_cpu_count == num_online_cpus())
acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0);
c3_cpu_count--; c3_cpu_count--;
spin_unlock(&c3_lock); spin_unlock(&c3_lock);
} }
...@@ -1525,6 +1543,9 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, ...@@ -1525,6 +1543,9 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
/* TSC could halt in idle, so notify users */ /* TSC could halt in idle, so notify users */
mark_tsc_unstable("TSC halts in idle"); mark_tsc_unstable("TSC halts in idle");
#endif #endif
sleep_ticks = ticks_elapsed(t1, t2);
/* Tell the scheduler how much we idled: */
sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS);
local_irq_enable(); local_irq_enable();
current_thread_info()->status |= TS_POLLING; current_thread_info()->status |= TS_POLLING;
...@@ -1532,7 +1553,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, ...@@ -1532,7 +1553,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
cx->usage++; cx->usage++;
acpi_state_timer_broadcast(pr, cx, 0); acpi_state_timer_broadcast(pr, cx, 0);
cx->time += ticks_elapsed(t1, t2); cx->time += sleep_ticks;
return ticks_elapsed_in_us(t1, t2); return ticks_elapsed_in_us(t1, t2);
} }
...@@ -1584,12 +1605,14 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) ...@@ -1584,12 +1605,14 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
case ACPI_STATE_C1: case ACPI_STATE_C1:
state->flags |= CPUIDLE_FLAG_SHALLOW; state->flags |= CPUIDLE_FLAG_SHALLOW;
state->enter = acpi_idle_enter_c1; state->enter = acpi_idle_enter_c1;
dev->safe_state = state;
break; break;
case ACPI_STATE_C2: case ACPI_STATE_C2:
state->flags |= CPUIDLE_FLAG_BALANCED; state->flags |= CPUIDLE_FLAG_BALANCED;
state->flags |= CPUIDLE_FLAG_TIME_VALID; state->flags |= CPUIDLE_FLAG_TIME_VALID;
state->enter = acpi_idle_enter_simple; state->enter = acpi_idle_enter_simple;
dev->safe_state = state;
break; break;
case ACPI_STATE_C3: case ACPI_STATE_C3:
...@@ -1610,14 +1633,6 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) ...@@ -1610,14 +1633,6 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
if (!count) if (!count)
return -EINVAL; return -EINVAL;
/* find the deepest state that can handle active BM */
if (pr->flags.bm_check) {
for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++)
if (pr->power.states[i].type == ACPI_STATE_C3)
break;
pr->power.bm_state = &pr->power.states[i-1];
}
return 0; return 0;
} }
......
This diff is collapsed.
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS_POWER
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
...@@ -88,7 +88,7 @@ MODULE_DEVICE_TABLE(acpi, sbs_device_ids); ...@@ -88,7 +88,7 @@ MODULE_DEVICE_TABLE(acpi, sbs_device_ids);
struct acpi_battery { struct acpi_battery {
struct power_supply bat; struct power_supply bat;
struct acpi_sbs *sbs; struct acpi_sbs *sbs;
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS_POWER
struct proc_dir_entry *proc_entry; struct proc_dir_entry *proc_entry;
#endif #endif
unsigned long update_time; unsigned long update_time;
...@@ -113,6 +113,7 @@ struct acpi_battery { ...@@ -113,6 +113,7 @@ struct acpi_battery {
u16 spec; u16 spec;
u8 id; u8 id;
u8 present:1; u8 present:1;
u8 have_sysfs_alarm:1;
}; };
#define to_acpi_battery(x) container_of(x, struct acpi_battery, bat); #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat);
...@@ -122,7 +123,7 @@ struct acpi_sbs { ...@@ -122,7 +123,7 @@ struct acpi_sbs {
struct acpi_device *device; struct acpi_device *device;
struct acpi_smb_hc *hc; struct acpi_smb_hc *hc;
struct mutex lock; struct mutex lock;
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS_POWER
struct proc_dir_entry *charger_entry; struct proc_dir_entry *charger_entry;
#endif #endif
struct acpi_battery battery[MAX_SBS_BAT]; struct acpi_battery battery[MAX_SBS_BAT];
...@@ -468,7 +469,7 @@ static struct device_attribute alarm_attr = { ...@@ -468,7 +469,7 @@ static struct device_attribute alarm_attr = {
FS Interface (/proc/acpi) FS Interface (/proc/acpi)
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS_POWER
/* Generic Routines */ /* Generic Routines */
static int static int
acpi_sbs_add_fs(struct proc_dir_entry **dir, acpi_sbs_add_fs(struct proc_dir_entry **dir,
...@@ -789,7 +790,7 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) ...@@ -789,7 +790,7 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id)
return result; return result;
sprintf(battery->name, ACPI_BATTERY_DIR_NAME, id); sprintf(battery->name, ACPI_BATTERY_DIR_NAME, id);
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS_POWER
acpi_sbs_add_fs(&battery->proc_entry, acpi_battery_dir, acpi_sbs_add_fs(&battery->proc_entry, acpi_battery_dir,
battery->name, &acpi_battery_info_fops, battery->name, &acpi_battery_info_fops,
&acpi_battery_state_fops, &acpi_battery_alarm_fops, &acpi_battery_state_fops, &acpi_battery_alarm_fops,
...@@ -808,7 +809,13 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) ...@@ -808,7 +809,13 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id)
} }
battery->bat.get_property = acpi_sbs_battery_get_property; battery->bat.get_property = acpi_sbs_battery_get_property;
result = power_supply_register(&sbs->device->dev, &battery->bat); result = power_supply_register(&sbs->device->dev, &battery->bat);
device_create_file(battery->bat.dev, &alarm_attr); if (result)
goto end;
result = device_create_file(battery->bat.dev, &alarm_attr);
if (result)
goto end;
battery->have_sysfs_alarm = 1;
end:
printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n", printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n",
ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
battery->name, sbs->battery->present ? "present" : "absent"); battery->name, sbs->battery->present ? "present" : "absent");
...@@ -817,14 +824,16 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) ...@@ -817,14 +824,16 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id)
static void acpi_battery_remove(struct acpi_sbs *sbs, int id) static void acpi_battery_remove(struct acpi_sbs *sbs, int id)
{ {
if (sbs->battery[id].bat.dev) struct acpi_battery *battery = &sbs->battery[id];
device_remove_file(sbs->battery[id].bat.dev, &alarm_attr);
power_supply_unregister(&sbs->battery[id].bat); if (battery->bat.dev) {
#ifdef CONFIG_ACPI_PROCFS if (battery->have_sysfs_alarm)
if (sbs->battery[id].proc_entry) { device_remove_file(battery->bat.dev, &alarm_attr);
acpi_sbs_remove_fs(&(sbs->battery[id].proc_entry), power_supply_unregister(&battery->bat);
acpi_battery_dir);
} }
#ifdef CONFIG_ACPI_PROCFS_POWER
if (battery->proc_entry)
acpi_sbs_remove_fs(&battery->proc_entry, acpi_battery_dir);
#endif #endif
} }
...@@ -835,7 +844,7 @@ static int acpi_charger_add(struct acpi_sbs *sbs) ...@@ -835,7 +844,7 @@ static int acpi_charger_add(struct acpi_sbs *sbs)
result = acpi_ac_get_present(sbs); result = acpi_ac_get_present(sbs);
if (result) if (result)
goto end; goto end;
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS_POWER
result = acpi_sbs_add_fs(&sbs->charger_entry, acpi_ac_dir, result = acpi_sbs_add_fs(&sbs->charger_entry, acpi_ac_dir,
ACPI_AC_DIR_NAME, NULL, ACPI_AC_DIR_NAME, NULL,
&acpi_ac_state_fops, NULL, sbs); &acpi_ac_state_fops, NULL, sbs);
...@@ -859,7 +868,7 @@ static void acpi_charger_remove(struct acpi_sbs *sbs) ...@@ -859,7 +868,7 @@ static void acpi_charger_remove(struct acpi_sbs *sbs)
{ {
if (sbs->charger.dev) if (sbs->charger.dev)
power_supply_unregister(&sbs->charger); power_supply_unregister(&sbs->charger);
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS_POWER
if (sbs->charger_entry) if (sbs->charger_entry)
acpi_sbs_remove_fs(&sbs->charger_entry, acpi_ac_dir); acpi_sbs_remove_fs(&sbs->charger_entry, acpi_ac_dir);
#endif #endif
...@@ -965,7 +974,7 @@ static int acpi_sbs_remove(struct acpi_device *device, int type) ...@@ -965,7 +974,7 @@ static int acpi_sbs_remove(struct acpi_device *device, int type)
static void acpi_sbs_rmdirs(void) static void acpi_sbs_rmdirs(void)
{ {
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS_POWER
if (acpi_ac_dir) { if (acpi_ac_dir) {
acpi_unlock_ac_dir(acpi_ac_dir); acpi_unlock_ac_dir(acpi_ac_dir);
acpi_ac_dir = NULL; acpi_ac_dir = NULL;
...@@ -1004,7 +1013,7 @@ static int __init acpi_sbs_init(void) ...@@ -1004,7 +1013,7 @@ static int __init acpi_sbs_init(void)
if (acpi_disabled) if (acpi_disabled)
return -ENODEV; return -ENODEV;
#ifdef CONFIG_ACPI_PROCFS #ifdef CONFIG_ACPI_PROCFS_POWER
acpi_ac_dir = acpi_lock_ac_dir(); acpi_ac_dir = acpi_lock_ac_dir();
if (!acpi_ac_dir) if (!acpi_ac_dir)
return -ENODEV; return -ENODEV;
......
...@@ -449,7 +449,7 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags) ...@@ -449,7 +449,7 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address, u8 flags)
/* XSDT has NULL entry, RSDT is used */ /* XSDT has NULL entry, RSDT is used */
address = rsdt_address; address = rsdt_address;
table_entry_size = sizeof(u32); table_entry_size = sizeof(u32);
ACPI_WARNING((AE_INFO, "BIOS XSDT has NULL entry," ACPI_WARNING((AE_INFO, "BIOS XSDT has NULL entry, "
"using RSDT")); "using RSDT"));
} }
} }
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/input.h> #include <linux/input.h>
...@@ -135,8 +136,8 @@ struct acpi_video_bus { ...@@ -135,8 +136,8 @@ struct acpi_video_bus {
u8 attached_count; u8 attached_count;
struct acpi_video_bus_cap cap; struct acpi_video_bus_cap cap;
struct acpi_video_bus_flags flags; struct acpi_video_bus_flags flags;
struct semaphore sem;
struct list_head video_device_list; struct list_head video_device_list;
struct mutex device_list_lock; /* protects video_device_list */
struct proc_dir_entry *dir; struct proc_dir_entry *dir;
struct input_dev *input; struct input_dev *input;
char phys[32]; /* for input device */ char phys[32]; /* for input device */
...@@ -896,7 +897,7 @@ acpi_video_device_write_brightness(struct file *file, ...@@ -896,7 +897,7 @@ acpi_video_device_write_brightness(struct file *file,
{ {
struct seq_file *m = file->private_data; struct seq_file *m = file->private_data;
struct acpi_video_device *dev = m->private; struct acpi_video_device *dev = m->private;
char str[4] = { 0 }; char str[5] = { 0 };
unsigned int level = 0; unsigned int level = 0;
int i; int i;
...@@ -1436,9 +1437,9 @@ acpi_video_bus_get_one_device(struct acpi_device *device, ...@@ -1436,9 +1437,9 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
return -ENODEV; return -ENODEV;
} }
down(&video->sem); mutex_lock(&video->device_list_lock);
list_add_tail(&data->entry, &video->video_device_list); list_add_tail(&data->entry, &video->video_device_list);
up(&video->sem); mutex_unlock(&video->device_list_lock);
acpi_video_device_add_fs(device); acpi_video_device_add_fs(device);
...@@ -1462,12 +1463,14 @@ acpi_video_bus_get_one_device(struct acpi_device *device, ...@@ -1462,12 +1463,14 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
static void acpi_video_device_rebind(struct acpi_video_bus *video) static void acpi_video_device_rebind(struct acpi_video_bus *video)
{ {
struct list_head *node, *next; struct acpi_video_device *dev;
list_for_each_safe(node, next, &video->video_device_list) {
struct acpi_video_device *dev = mutex_lock(&video->device_list_lock);
container_of(node, struct acpi_video_device, entry);
list_for_each_entry(dev, &video->video_device_list, entry)
acpi_video_device_bind(video, dev); acpi_video_device_bind(video, dev);
}
mutex_unlock(&video->device_list_lock);
} }
/* /*
...@@ -1592,30 +1595,33 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video) ...@@ -1592,30 +1595,33 @@ static int acpi_video_device_enumerate(struct acpi_video_bus *video)
static int acpi_video_switch_output(struct acpi_video_bus *video, int event) static int acpi_video_switch_output(struct acpi_video_bus *video, int event)
{ {
struct list_head *node, *next; struct list_head *node;
struct acpi_video_device *dev = NULL; struct acpi_video_device *dev = NULL;
struct acpi_video_device *dev_next = NULL; struct acpi_video_device *dev_next = NULL;
struct acpi_video_device *dev_prev = NULL; struct acpi_video_device *dev_prev = NULL;
unsigned long state; unsigned long state;
int status = 0; int status = 0;
mutex_lock(&video->device_list_lock);
list_for_each_safe(node, next, &video->video_device_list) { list_for_each(node, &video->video_device_list) {
dev = container_of(node, struct acpi_video_device, entry); dev = container_of(node, struct acpi_video_device, entry);
status = acpi_video_device_get_state(dev, &state); status = acpi_video_device_get_state(dev, &state);
if (state & 0x2) { if (state & 0x2) {
dev_next = dev_next = container_of(node->next,
container_of(node->next, struct acpi_video_device, struct acpi_video_device, entry);
entry); dev_prev = container_of(node->prev,
dev_prev = struct acpi_video_device, entry);
container_of(node->prev, struct acpi_video_device,
entry);
goto out; goto out;
} }
} }
dev_next = container_of(node->next, struct acpi_video_device, entry); dev_next = container_of(node->next, struct acpi_video_device, entry);
dev_prev = container_of(node->prev, struct acpi_video_device, entry); dev_prev = container_of(node->prev, struct acpi_video_device, entry);
out:
out:
mutex_unlock(&video->device_list_lock);
switch (event) { switch (event) {
case ACPI_VIDEO_NOTIFY_CYCLE: case ACPI_VIDEO_NOTIFY_CYCLE:
case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT: case ACPI_VIDEO_NOTIFY_NEXT_OUTPUT:
...@@ -1691,24 +1697,17 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video, ...@@ -1691,24 +1697,17 @@ acpi_video_bus_get_devices(struct acpi_video_bus *video,
struct acpi_device *device) struct acpi_device *device)
{ {
int status = 0; int status = 0;
struct list_head *node, *next; struct acpi_device *dev;
acpi_video_device_enumerate(video); acpi_video_device_enumerate(video);
list_for_each_safe(node, next, &device->children) { list_for_each_entry(dev, &device->children, node) {
struct acpi_device *dev =
list_entry(node, struct acpi_device, node);
if (!dev)
continue;
status = acpi_video_bus_get_one_device(dev, video); status = acpi_video_bus_get_one_device(dev, video);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status, "Cant attach device")); ACPI_EXCEPTION((AE_INFO, status, "Cant attach device"));
continue; continue;
} }
} }
return status; return status;
} }
...@@ -1724,9 +1723,6 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device) ...@@ -1724,9 +1723,6 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device)
video = device->video; video = device->video;
down(&video->sem);
list_del(&device->entry);
up(&video->sem);
acpi_video_device_remove_fs(device->dev); acpi_video_device_remove_fs(device->dev);
status = acpi_remove_notify_handler(device->dev->handle, status = acpi_remove_notify_handler(device->dev->handle,
...@@ -1734,32 +1730,34 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device) ...@@ -1734,32 +1730,34 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device)
acpi_video_device_notify); acpi_video_device_notify);
backlight_device_unregister(device->backlight); backlight_device_unregister(device->backlight);
video_output_unregister(device->output_dev); video_output_unregister(device->output_dev);
return 0; return 0;
} }
static int acpi_video_bus_put_devices(struct acpi_video_bus *video) static int acpi_video_bus_put_devices(struct acpi_video_bus *video)
{ {
int status; int status;
struct list_head *node, *next; struct acpi_video_device *dev, *next;
mutex_lock(&video->device_list_lock);
list_for_each_safe(node, next, &video->video_device_list) { list_for_each_entry_safe(dev, next, &video->video_device_list, entry) {
struct acpi_video_device *data =
list_entry(node, struct acpi_video_device, entry);
if (!data)
continue;
status = acpi_video_bus_put_one_device(data); status = acpi_video_bus_put_one_device(dev);
if (ACPI_FAILURE(status)) if (ACPI_FAILURE(status))
printk(KERN_WARNING PREFIX printk(KERN_WARNING PREFIX
"hhuuhhuu bug in acpi video driver.\n"); "hhuuhhuu bug in acpi video driver.\n");
if (data->brightness) if (dev->brightness) {
kfree(data->brightness->levels); kfree(dev->brightness->levels);
kfree(data->brightness); kfree(dev->brightness);
kfree(data); }
list_del(&dev->entry);
kfree(dev);
} }
mutex_unlock(&video->device_list_lock);
return 0; return 0;
} }
...@@ -1782,9 +1780,6 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data) ...@@ -1782,9 +1780,6 @@ static void acpi_video_bus_notify(acpi_handle handle, u32 event, void *data)
struct input_dev *input; struct input_dev *input;
int keycode; int keycode;
printk("video bus notify\n");
if (!video) if (!video)
return; return;
...@@ -1897,14 +1892,10 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) ...@@ -1897,14 +1892,10 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data)
static int instance; static int instance;
static int acpi_video_bus_add(struct acpi_device *device) static int acpi_video_bus_add(struct acpi_device *device)
{ {
int result = 0; acpi_status status;
acpi_status status = 0; struct acpi_video_bus *video;
struct acpi_video_bus *video = NULL;
struct input_dev *input; struct input_dev *input;
int error;
if (!device)
return -EINVAL;
video = kzalloc(sizeof(struct acpi_video_bus), GFP_KERNEL); video = kzalloc(sizeof(struct acpi_video_bus), GFP_KERNEL);
if (!video) if (!video)
...@@ -1923,15 +1914,15 @@ static int acpi_video_bus_add(struct acpi_device *device) ...@@ -1923,15 +1914,15 @@ static int acpi_video_bus_add(struct acpi_device *device)
acpi_driver_data(device) = video; acpi_driver_data(device) = video;
acpi_video_bus_find_cap(video); acpi_video_bus_find_cap(video);
result = acpi_video_bus_check(video); error = acpi_video_bus_check(video);
if (result) if (error)
goto end; goto err_free_video;
result = acpi_video_bus_add_fs(device); error = acpi_video_bus_add_fs(device);
if (result) if (error)
goto end; goto err_free_video;
init_MUTEX(&video->sem); mutex_init(&video->device_list_lock);
INIT_LIST_HEAD(&video->video_device_list); INIT_LIST_HEAD(&video->video_device_list);
acpi_video_bus_get_devices(video, device); acpi_video_bus_get_devices(video, device);
...@@ -1943,16 +1934,15 @@ static int acpi_video_bus_add(struct acpi_device *device) ...@@ -1943,16 +1934,15 @@ static int acpi_video_bus_add(struct acpi_device *device)
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Error installing notify handler\n")); "Error installing notify handler\n"));
acpi_video_bus_stop_devices(video); error = -ENODEV;
acpi_video_bus_put_devices(video); goto err_stop_video;
kfree(video->attached_array);
acpi_video_bus_remove_fs(device);
result = -ENODEV;
goto end;
} }
video->input = input = input_allocate_device(); video->input = input = input_allocate_device();
if (!input) {
error = -ENOMEM;
goto err_uninstall_notify;
}
snprintf(video->phys, sizeof(video->phys), snprintf(video->phys, sizeof(video->phys),
"%s/video/input0", acpi_device_hid(video->device)); "%s/video/input0", acpi_device_hid(video->device));
...@@ -1961,6 +1951,7 @@ static int acpi_video_bus_add(struct acpi_device *device) ...@@ -1961,6 +1951,7 @@ static int acpi_video_bus_add(struct acpi_device *device)
input->phys = video->phys; input->phys = video->phys;
input->id.bustype = BUS_HOST; input->id.bustype = BUS_HOST;
input->id.product = 0x06; input->id.product = 0x06;
input->dev.parent = &device->dev;
input->evbit[0] = BIT(EV_KEY); input->evbit[0] = BIT(EV_KEY);
set_bit(KEY_SWITCHVIDEOMODE, input->keybit); set_bit(KEY_SWITCHVIDEOMODE, input->keybit);
set_bit(KEY_VIDEO_NEXT, input->keybit); set_bit(KEY_VIDEO_NEXT, input->keybit);
...@@ -1971,18 +1962,10 @@ static int acpi_video_bus_add(struct acpi_device *device) ...@@ -1971,18 +1962,10 @@ static int acpi_video_bus_add(struct acpi_device *device)
set_bit(KEY_BRIGHTNESS_ZERO, input->keybit); set_bit(KEY_BRIGHTNESS_ZERO, input->keybit);
set_bit(KEY_DISPLAY_OFF, input->keybit); set_bit(KEY_DISPLAY_OFF, input->keybit);
set_bit(KEY_UNKNOWN, input->keybit); set_bit(KEY_UNKNOWN, input->keybit);
result = input_register_device(input);
if (result) {
acpi_remove_notify_handler(video->device->handle,
ACPI_DEVICE_NOTIFY,
acpi_video_bus_notify);
acpi_video_bus_stop_devices(video);
acpi_video_bus_put_devices(video);
kfree(video->attached_array);
acpi_video_bus_remove_fs(device);
goto end;
}
error = input_register_device(input);
if (error)
goto err_free_input_dev;
printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n", printk(KERN_INFO PREFIX "%s [%s] (multi-head: %s rom: %s post: %s)\n",
ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device), ACPI_VIDEO_DEVICE_NAME, acpi_device_bid(device),
...@@ -1990,11 +1973,23 @@ static int acpi_video_bus_add(struct acpi_device *device) ...@@ -1990,11 +1973,23 @@ static int acpi_video_bus_add(struct acpi_device *device)
video->flags.rom ? "yes" : "no", video->flags.rom ? "yes" : "no",
video->flags.post ? "yes" : "no"); video->flags.post ? "yes" : "no");
end: return 0;
if (result)
kfree(video); err_free_input_dev:
input_free_device(input);
err_uninstall_notify:
acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY,
acpi_video_bus_notify);
err_stop_video:
acpi_video_bus_stop_devices(video);
acpi_video_bus_put_devices(video);
kfree(video->attached_array);
acpi_video_bus_remove_fs(device);
err_free_video:
kfree(video);
acpi_driver_data(device) = NULL;
return result; return error;
} }
static int acpi_video_bus_remove(struct acpi_device *device, int type) static int acpi_video_bus_remove(struct acpi_device *device, int type)
......
This diff is collapsed.
...@@ -84,7 +84,7 @@ ...@@ -84,7 +84,7 @@
/* ThinkPad CMOS NVRAM constants */ /* ThinkPad CMOS NVRAM constants */
#define TP_NVRAM_ADDR_BRIGHTNESS 0x5e #define TP_NVRAM_ADDR_BRIGHTNESS 0x5e
#define TP_NVRAM_MASK_LEVEL_BRIGHTNESS 0x07 #define TP_NVRAM_MASK_LEVEL_BRIGHTNESS 0x0f
#define TP_NVRAM_POS_LEVEL_BRIGHTNESS 0 #define TP_NVRAM_POS_LEVEL_BRIGHTNESS 0
#define onoff(status,bit) ((status) & (1 << (bit)) ? "on" : "off") #define onoff(status,bit) ((status) & (1 << (bit)) ? "on" : "off")
...@@ -246,6 +246,7 @@ static struct { ...@@ -246,6 +246,7 @@ static struct {
u32 hotkey_wlsw:1; u32 hotkey_wlsw:1;
u32 light:1; u32 light:1;
u32 light_status:1; u32 light_status:1;
u32 bright_16levels:1;
u32 wan:1; u32 wan:1;
u32 fan_ctrl_status_undef:1; u32 fan_ctrl_status_undef:1;
u32 input_device_registered:1; u32 input_device_registered:1;
...@@ -338,6 +339,7 @@ static int bluetooth_write(char *buf); ...@@ -338,6 +339,7 @@ static int bluetooth_write(char *buf);
static struct backlight_device *ibm_backlight_device; static struct backlight_device *ibm_backlight_device;
static int brightness_offset = 0x31; static int brightness_offset = 0x31;
static int brightness_mode; 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 int brightness_init(struct ibm_init_struct *iibm);
static void brightness_exit(void); static void brightness_exit(void);
......
...@@ -75,6 +75,7 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res, ...@@ -75,6 +75,7 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res,
{ {
int i = 0; int i = 0;
int irq; int irq;
int p, t;
if (!valid_IRQ(gsi)) if (!valid_IRQ(gsi))
return; return;
...@@ -85,15 +86,22 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res, ...@@ -85,15 +86,22 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res,
if (i >= PNP_MAX_IRQ) if (i >= PNP_MAX_IRQ)
return; return;
#ifdef CONFIG_X86 /*
if (gsi < 16 && (triggering != ACPI_EDGE_SENSITIVE || * in IO-APIC mode, use overrided attribute. Two reasons:
polarity != ACPI_ACTIVE_HIGH)) { * 1. BIOS bug in DSDT
pnp_warn("BIOS BUG: legacy PNP IRQ %d should be edge trigger, " * 2. BIOS uses IO-APIC mode Interrupt Source Override
"active high", gsi); */
triggering = ACPI_EDGE_SENSITIVE; if (!acpi_get_override_irq(gsi, &t, &p)) {
polarity = ACPI_ACTIVE_HIGH; t = t ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
p = p ? ACPI_ACTIVE_LOW : ACPI_ACTIVE_HIGH;
if (triggering != t || polarity != p) {
pnp_warn("IRQ %d override to %s, %s",
gsi, t ? "edge":"level", p ? "low":"high");
triggering = t;
polarity = p;
}
} }
#endif
res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag res->irq_resource[i].flags = IORESOURCE_IRQ; // Also clears _UNSET flag
res->irq_resource[i].flags |= irq_flags(triggering, polarity); res->irq_resource[i].flags |= irq_flags(triggering, polarity);
......
...@@ -78,7 +78,6 @@ struct acpi_processor_cx { ...@@ -78,7 +78,6 @@ struct acpi_processor_cx {
struct acpi_processor_power { struct acpi_processor_power {
struct cpuidle_device dev; struct cpuidle_device dev;
struct acpi_processor_cx *state; struct acpi_processor_cx *state;
struct acpi_processor_cx *bm_state;
unsigned long bm_check_timestamp; unsigned long bm_check_timestamp;
u32 default_state; u32 default_state;
u32 bm_activity; u32 bm_activity;
......
...@@ -132,6 +132,11 @@ extern unsigned long acpi_realmode_flags; ...@@ -132,6 +132,11 @@ extern unsigned long acpi_realmode_flags;
int acpi_register_gsi (u32 gsi, int triggering, int polarity); int acpi_register_gsi (u32 gsi, int triggering, int polarity);
int acpi_gsi_to_irq (u32 gsi, unsigned int *irq); int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
#ifdef CONFIG_X86_IO_APIC
extern int acpi_get_override_irq(int bus_irq, int *trigger, int *polarity);
#else
#define acpi_get_override_irq(bus, trigger, polarity) (-1)
#endif
/* /*
* This function undoes the effect of one call to acpi_register_gsi(). * This function undoes the effect of one call to acpi_register_gsi().
* If this matches the last registration, any IRQ resources for gsi * If this matches the last registration, any IRQ resources for gsi
......
...@@ -92,6 +92,7 @@ struct cpuidle_device { ...@@ -92,6 +92,7 @@ struct cpuidle_device {
struct kobject kobj; struct kobject kobj;
struct completion kobj_unregister; struct completion kobj_unregister;
void *governor_data; void *governor_data;
struct cpuidle_state *safe_state;
}; };
DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices); DECLARE_PER_CPU(struct cpuidle_device *, cpuidle_devices);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment