ACPI patches pushed to linux-2.6.19-rc2
Subsystems (5)
Here are individual patches from the git pull request for 2.6.19-rc2
PATCH 1/28 ACPI: asus_acpi: W3000 support
From: Marek W <[email protected]>
Add support for W3000 (W3V) and indirectly fixes an issue with kmilo under KDE (it was triggering excessive LCD read error messages by querying asus_acpi module) allowing people (I am probably the only one who tested this) with W3000 to run kmilo.
--- drivers/acpi/asus_acpi.c | 17 ++++++++++++++++- 1 files changed, 16 insertions(+), 1 deletions(-)
drivers/acpi/asus_acpi.c +16 -1
@@ -138,6 +138,7 @@ struct asus_hotk { S2x,//S200 (J1 reported), Victor MP-XP7210 W1N ,//W1000N W5A ,//W5A +W3V ,//W3030V xxN,//M2400N, M3700N, M5200N, M6800N, S1300N, S5200N //(Centrino) END_MODEL
@@ -376,6 +377,17 @@ static struct model_data model_conf[END_ .display_get = "\\ADVG"}, { + .name = "W3V", + .mt_mled = "MLED", + .mt_wled = "WLED", + .mt_lcd_switch = xxN_PREFIX "_Q10", + .lcd_status = "\\BKLT", + .brightness_set = "SPLV", + .brightness_get = "GPLV", + .display_set = "SDSP", + .display_get = "\\INFB"}, + + { .name = "xxN", .mt_mled = "MLED",/* WLED present, but not controlled by ACPI */
@@ -1097,6 +1109,8 @@ static int asus_model_match(char *model)return A4G ; else if (strncmp(model, "W1N", 3) == 0) return W1N; + else if (strncmp(model, "W3V", 3) == 0) + return W3V; else if (strncmp(model, "W5A", 3) == 0) return W5A; else
@@ -1200,9 +1214,10 @@ static int asus_hotk_get_info(void) hotk->methods->mt_wled =NULL ;/* L5D's WLED is not controlled by ACPI */ else if (strncmp(string, "M2N", 3) == 0 || + strncmp(string, "W3V", 3) == 0 || strncmp(string, "S1N", 3) == 0) hotk->methods->mt_wled = "WLED"; - /* M2N and S1N have a usable WLED */ + /* M2N, S1N and W3V have a usable WLED */ else if (asus_info) { if (strncmp(asus_info->oem_table_id, "L1", 2) == 0) hotk->methods->mled_status = NULL;
Signature · 1 line
1.4.3.rc2.g23bed-dirty
PATCH 2/28 ACPI: ibm_acpi: Remove experimental status for brightness and volume.
In reply to Len BrownFrom: Stefan Schmidt <[email protected]>
The brightness and volume features from ibm-acpi are stable. The experimental flag is no longer needed.
--- drivers/acpi/ibm_acpi.c | 2 -- 1 files changed, 0 insertions(+), 2 deletions(-)
drivers/acpi/ibm_acpi.c +0 -2
@@ -1702,13 +1702,11 @@ #endif .name = "brightness", .read = brightness_read, .write = brightness_write, - .experimental = 1, }, { .name = "volume", .read = volume_read, .write = volume_write, - .experimental = 1, }, { .name = "fan",
Signature · 1 line
1.4.3.rc2.g23bed-dirty
PATCH 3/28 ACPI: ibm_acpi: Update documentation for brightness and volume.
In reply to Len BrownFrom: Stefan Schmidt <[email protected]>
Document the change of the experimental flag for brightness and volume.
--- Documentation/ibm-acpi.txt | 22 ++++++---------------- 1 files changed, 6 insertions(+), 16 deletions(-)
Documentation/ibm-acpi.txt +6 -16
@@ -30,8 +30,8 @@ detailed description): - ACPI sounds - temperature sensors - Experimental: embedded controller register dump - - Experimental: LCD brightness control - - Experimental: volume control + - LCD brightness control + - Volume control - Experimental: fan speed, fan enable/disable A compatibility table by model and feature is maintained on the web
@@ -523,13 +523,8 @@ registers contain the current battery ca with this, do send me your results (including some complete dumps with a description of the conditions when they were taken.) -EXPERIMENTAL: LCD brightness control -- /proc/acpi/ibm/brightness ------------------------------------------------------------------ - -This 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. +LCD brightness control -- /proc/acpi/ibm/brightness +--------------------------------------------------- This feature allows software control of the LCD brightness on ThinkPad models which don't have a hardware brightness slider. The available
@@ -542,13 +537,8 @@ commands are: The <level> number range is 0 to 7, although not all of them may be distinct. The current brightness level is shown in the file. -EXPERIMENTAL: Volume control -- /proc/acpi/ibm/volume ------------------------------------------------------ - -This 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. +Volume control -- /proc/acpi/ibm/volume +--------------------------------------- This feature allows volume control on ThinkPad models which don't have a hardware volume knob. The available commands are:
Signature · 1 line
1.4.3.rc2.g23bed-dirty
PATCH 4/28 ACPI: ibm_acpi: Documentation the wan feature.
In reply to Len BrownFrom: Stefan Schmidt <[email protected]>
Document the wan feature Jeremy Fitzhardinge added to ibm_acpi.
--- Documentation/ibm-acpi.txt | 18 ++++++++++++++++++ 1 files changed, 18 insertions(+), 0 deletions(-)
Documentation/ibm-acpi.txt +18 -0
@@ -33,6 +33,7 @@ detailed description): - LCD brightness control - Volume control - Experimental: fan speed, fan enable/disable + - Experimental: WAN enable and disable A compatibility table by model and feature is maintained on the web site, http://ibm-acpi.sf.net/. I appreciate any success or failure
@@ -601,6 +602,23 @@ with the following command: echo 'level <level>' > /proc/acpi/ibm/thermal +EXPERIMENTAL: WAN -- /proc/acpi/ibm/wan +--------------------------------------- + +This 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. + +This feature shows the presence and current state of a WAN (Sierra +Wireless EV-DO) device. If WAN is installed, the following commands can +be used: + + echo enable > /proc/acpi/ibm/wan + echo disable > /proc/acpi/ibm/wan + +It was tested on a Lenovo Thinkpad X60. It should probably work on other +Thinkpad models which come with this module installed. Multiple Commands, Module Parameters ------------------------------------
Signature · 1 line
1.4.3.rc2.g23bed-dirty
PATCH 5/28 ACPI: sbs: check for NULL device pointer
In reply to Len BrownFrom: Lebedev, Vladimir P <[email protected]>
--- drivers/acpi/sbs.c | 10 ++++++++-- 1 files changed, 8 insertions(+), 2 deletions(-)
drivers/acpi/sbs.c +8 -2
@@ -1685,10 +1685,16 @@ static int acpi_sbs_add(struct acpi_deviint acpi_sbs_remove (struct acpi_device *device,int type) { -struct acpi_sbs *sbs = (struct acpi_sbs *)acpi_driver_data (device); +struct acpi_sbs *sbs =NULL ;int id; -if (!device || !sbs) { +if (!device) { +return -EINVAL ; + } + + sbs = (struct acpi_sbs *)acpi_driver_data (device); + +if (!sbs) {return -EINVAL ; }
Signature · 1 line
1.4.3.rc2.g23bed-dirty
PATCH 6/28 ACPI: sbs: fix module_param() initializers
In reply to Len BrownFrom: Lebedev, Vladimir P <[email protected]>
--- drivers/acpi/sbs.c | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-)
drivers/acpi/sbs.c +5 -5
@@ -98,11 +98,11 @@ static int update_info_mode = UPDATE_INFstatic int update_time =UPDATE_TIME ;static int update_time2 =UPDATE_TIME2 ; -module_param (capacity_mode, int,CAPACITY_UNIT ); -module_param (update_mode, int,UPDATE_MODE ); -module_param (update_info_mode, int,UPDATE_INFO_MODE ); -module_param (update_time, int,UPDATE_TIME ); -module_param (update_time2, int,UPDATE_TIME2 ); +module_param (capacity_mode, int,0 ); +module_param (update_mode, int,0 ); +module_param (update_info_mode, int,0 ); +module_param (update_time, int,0 ); +module_param (update_time2, int,0 );static int acpi_sbs_add (struct acpi_device *device);static int acpi_sbs_remove (struct acpi_device *device,int type);
Signature · 1 line
1.4.3.rc2.g23bed-dirty
PATCH 7/28 ACPI: Processor native C-states using MWAIT
In reply to Len BrownFrom: Venkatesh Pallipadi <[email protected]>
Intel processors starting with the Core Duo support support processor native C-state using the MWAIT instruction.
Refer: Intel Architecture Software Developer's Manual
http://www.intel.com/design/Pentium4/manuals/253668.htm
Platform firmware exports the support for Native C-state to OS using ACPI _PDC and _CST methods.
Refer: Intel Processor Vendor-Specific ACPI: Interface Specification
http://www.intel.com/technology/iapc/acpi/downloads/302223.htm
With Processor Native C-state, we use 'MWAIT' instruction on the processor to enter different C-states (C1, C2, C3). We won't use the special IO ports to enter C-state and no SMM mode etc required to enter C-state. Overall this will mean better C-state support.
One major advantage of using MWAIT for all C-states is, with this and "treat interrupt as break event" feature of MWAIT, we can now get accurate timing for the time spent in C1, C2, .. states.
--- arch/i386/kernel/acpi/cstate.c | 122 +++++++++++++++++++++++++++++++++++++++- arch/i386/kernel/process.c | 22 +++++-- arch/x86_64/kernel/process.c | 22 +++++-- drivers/acpi/processor_idle.c | 101 ++++++++++++++++++++------------ include/acpi/pdc_intel.h | 9 ++- include/acpi/processor.h | 18 ++++++ include/asm-i386/processor.h | 2 + include/asm-x86_64/processor.h | 2 + 8 files changed, 242 insertions(+), 56 deletions(-)
arch/i386/kernel/acpi/cstate.c +121 -1
@@ -10,6 +10,7 @@ #include <linux/kernel.h>#include <linux/module.h> #include <linux/init.h> #include <linux/acpi.h> +#include <linux/cpu.h> #include <acpi/processor.h> #include <asm/acpi.h>
@@ -41,5 +42,124 @@ void acpi_processor_power_init_bm_check( flags->bm_check =1 ; } } -EXPORT_SYMBOL (acpi_processor_power_init_bm_check); + +/* The code below handles cstate entry with monitor-mwait pair on Intel*/ + +struct cstate_entry_s { +struct { +unsigned int eax; +unsigned int ecx; + } states[ACPI_PROCESSOR_MAX_POWER ]; +}; +static struct cstate_entry_s *cpu_cstate_entry;/* per CPU ptr */ + +static short mwait_supported[ACPI_PROCESSOR_MAX_POWER ]; + +#define MWAIT_SUBSTATE_MASK (0xf) +#define MWAIT_SUBSTATE_SIZE (4) + +#define CPUID_MWAIT_LEAF (5) +#define CPUID5_ECX_EXTENSIONS_SUPPORTED (0x1) +#define CPUID5_ECX_INTERRUPT_BREAK (0x2) + +#define MWAIT_ECX_INTERRUPT_BREAK (0x1) + +#define NATIVE_CSTATE_BEYOND_HALT (2) + +int acpi_processor_ffh_cstate_probe (unsigned int cpu, +struct acpi_processor_cx *cx,struct acpi_power_register *reg) +{ +struct cstate_entry_s *percpu_entry; +struct cpuinfo_x86 *c = cpu_data + cpu; + +cpumask_t saved_mask; +int retval; +unsigned int eax, ebx, ecx, edx; +unsigned int edx_part; +unsigned int cstate_type;/* C-state type and not ACPI C-state type */ +unsigned int num_cstate_subtype; + +if (!cpu_cstate_entry || c->cpuid_level <CPUID_MWAIT_LEAF ) +return -1 ; + +if (reg->bit_offset !=NATIVE_CSTATE_BEYOND_HALT ) +return -1 ; + + percpu_entry =per_cpu_ptr (cpu_cstate_entry, cpu); + percpu_entry->states[cx->index].eax =0 ; + percpu_entry->states[cx->index].ecx =0 ; + +/* Make sure we are running on right CPU */ + saved_mask = current->cpus_allowed; + retval =set_cpus_allowed (current,cpumask_of_cpu (cpu)); +if (retval) +return -1 ; + +cpuid (CPUID_MWAIT_LEAF , &eax, &ebx, &ecx, &edx); + +/* Check whether this particular cx_type (in CST) is supported or not */ + cstate_type = (cx->address >>MWAIT_SUBSTATE_SIZE ) +1 ; + edx_part = edx >> (cstate_type *MWAIT_SUBSTATE_SIZE ); + num_cstate_subtype = edx_part &MWAIT_SUBSTATE_MASK ; + + retval =0 ; +if (num_cstate_subtype < (cx->address &MWAIT_SUBSTATE_MASK )) { + retval =-1 ; + goto out; + } + +/* mwait ecx extensions INTERRUPT_BREAK should be supported for C2/C3 */ +if (!(ecx &CPUID5_ECX_EXTENSIONS_SUPPORTED ) || + !(ecx &CPUID5_ECX_INTERRUPT_BREAK )) { + retval =-1 ; + goto out; + } + percpu_entry->states[cx->index].ecx =MWAIT_ECX_INTERRUPT_BREAK ; + +/* Use the hint in CST */ + percpu_entry->states[cx->index].eax = cx->address; + +if (!mwait_supported[cstate_type]) { + mwait_supported[cstate_type] =1 ; +printk (KERN_DEBUG "Monitor-Mwait will be used to enter C-%d " +"state\n" , cx->type); + } + +out: +set_cpus_allowed (current, saved_mask); +return retval; +} +EXPORT_SYMBOL_GPL (acpi_processor_ffh_cstate_probe); + +void acpi_processor_ffh_cstate_enter (struct acpi_processor_cx *cx) +{ +unsigned int cpu =smp_processor_id (); +struct cstate_entry_s *percpu_entry; + + percpu_entry =per_cpu_ptr (cpu_cstate_entry, cpu); +mwait_idle_with_hints (percpu_entry->states[cx->index].eax, + percpu_entry->states[cx->index].ecx); +} +EXPORT_SYMBOL_GPL (acpi_processor_ffh_cstate_enter); + +static int __init ffh_cstate_init (void ) +{ +struct cpuinfo_x86 *c = &boot_cpu_data; +if (c->x86_vendor !=X86_VENDOR_INTEL ) +return -1 ; + + cpu_cstate_entry = alloc_percpu(struct cstate_entry_s); +return 0 ; +} + +static void __exit ffh_cstate_exit(void) +{ +if (cpu_cstate_entry) { +free_percpu (cpu_cstate_entry); + cpu_cstate_entry =NULL ; + } +} + +arch_initcall (ffh_cstate_init); +__exitcall (ffh_cstate_exit);
arch/i386/kernel/process.c +15 -7
@@ -236,20 +236,28 @@ EXPORT_SYMBOL_GPL(cpu_idle_wait);* We execute MONITOR against need_resched and enter optimized wait state * through MWAIT. Whenever someone changes need_resched, we would be woken * up from MWAIT (without an IPI). +* +* New with Core Duo processors, MWAIT can take some hints based on CPU +* capability. */ -static void mwait_idle (void ) +void mwait_idle_with_hints (unsigned long eax,unsigned long ecx) { -local_irq_enable (); - -while (!need_resched ()) { +if (!need_resched ()) {__monitor ((void *)¤t_thread_info ()->flags,0 ,0 );smp_mb (); -if (need_resched ()) -break ; -__mwait (0 ,0 ); +if (!need_resched ()) +__mwait (eax, ecx); } } +/* Default MONITOR/MWAIT with no hints, used for default C1 state */ +static void mwait_idle (void ) +{ +local_irq_enable (); +while (!need_resched ()) +mwait_idle_with_hints (0 ,0 ); +} +void __devinit select_idle_routine (const struct cpuinfo_x86 *c) {if (cpu_has (c,X86_FEATURE_MWAIT )) {
arch/x86_64/kernel/process.c +15 -7
@@ -238,20 +238,28 @@ void cpu_idle (void)* We execute MONITOR against need_resched and enter optimized wait state * through MWAIT. Whenever someone changes need_resched, we would be woken * up from MWAIT (without an IPI). +* +* New with Core Duo processors, MWAIT can take some hints based on CPU +* capability. */ -static void mwait_idle (void ) +void mwait_idle_with_hints (unsigned long eax,unsigned long ecx) { -local_irq_enable (); - -while (!need_resched ()) { +if (!need_resched ()) {__monitor ((void *)¤t_thread_info ()->flags,0 ,0 );smp_mb (); -if (need_resched ()) -break ; -__mwait (0 ,0 ); +if (!need_resched ()) +__mwait (eax, ecx); } } +/* Default MONITOR/MWAIT with no hints, used for default C1 state */ +static void mwait_idle (void ) +{ +local_irq_enable (); +while (!need_resched ()) +mwait_idle_with_hints (0 ,0 ); +} +void __cpuinit select_idle_routine (const struct cpuinfo_x86 *c) {static int printed;
drivers/acpi/processor_idle.c +63 -38
155 lines not on this page · raw message
include/acpi/pdc_intel.h +6 -3
@@ -13,6 +13,7 @@ #define ACPI_PDC_SMP_P_SWCOORD (0x0020)#define ACPI_PDC_SMP_C_SWCOORD (0x0040)#define ACPI_PDC_SMP_T_SWCOORD (0x0080)#define ACPI_PDC_C_C1_FFH (0x0100) +#define ACPI_PDC_C_C2C3_FFH (0x0200)#define ACPI_PDC_EST_CAPABILITY_SMP (ACPI_PDC_SMP_C1PT | \ ACPI_PDC_C_C1_HALT | \
@@ -23,8 +24,10 @@ #define ACPI_PDC_EST_CAPABILITY_SWSMP (A ACPI_PDC_SMP_P_SWCOORD | \ ACPI_PDC_P_FFH) -#define ACPI_PDC_C_CAPABILITY_SMP (ACPI_PDC_SMP_C2C3 | \ - ACPI_PDC_SMP_C1PT | \ - ACPI_PDC_C_C1_HALT) +#define ACPI_PDC_C_CAPABILITY_SMP (ACPI_PDC_SMP_C2C3 | \ + ACPI_PDC_SMP_C1PT | \ + ACPI_PDC_C_C1_HALT | \ + ACPI_PDC_C_C1_FFH | \ + ACPI_PDC_C_C2C3_FFH)#endif /* __PDC_INTEL_H__ */
include/acpi/processor.h +18 -0
@@ -29,6 +29,9 @@ #define DOMAIN_COORD_TYPE_SW_ALL 0xfc#define DOMAIN_COORD_TYPE_SW_ANY 0xfd#define DOMAIN_COORD_TYPE_HW_ALL 0xfe +#define ACPI_CSTATE_SYSTEMIO (0) +#define ACPI_CSTATE_FFH (1) +/* Power Management */ struct acpi_processor_cx ;
@@ -58,6 +61,8 @@ struct acpi_processor_cx {u8 valid;u8 type;u32 address; +u8 space_id; +u8 index;u32 latency;u32 latency_ticks;u32 power;
@@ -206,6 +211,9 @@ void arch_acpi_processor_init_pdc(struct#ifdef ARCH_HAS_POWER_INIT void acpi_processor_power_init_bm_check (struct acpi_processor_flags *flags,unsigned int cpu); +int acpi_processor_ffh_cstate_probe (unsigned int cpu, +struct acpi_processor_cx *cx,struct acpi_power_register *reg); +void acpi_processor_ffh_cstate_enter (struct acpi_processor_cx *cstate);#else static inline void acpi_processor_power_init_bm_check (struct acpi_processor_flags
@@ -214,6 +222,16 @@ static inline void acpi_processor_power_ flags->bm_check =1 ; return; } +static inline int acpi_processor_ffh_cstate_probe (unsigned int cpu, +struct acpi_processor_cx *cx,struct acpi_power_register *reg) +{ +return -1 ; +} +static inline void acpi_processor_ffh_cstate_enter ( +struct acpi_processor_cx *cstate) +{ +return ; +}#endif /* in processor_perflib.c */
include/asm-i386/processor.h +2 -0
@@ -306,6 +306,8 @@ static inline void __mwait(unsigned long : :"a" (eax), "c" (ecx)); } +extern void mwait_idle_with_hints (unsigned long eax,unsigned long ecx); +/* from system description table in BIOS. Mostly for MCA use, but others may find it useful. */ extern unsigned int machine_id;
include/asm-x86_64/processor.h +2 -0
@@ -475,6 +475,8 @@ static inline void __mwait(unsigned long : :"a" (eax), "c" (ecx)); } +extern void mwait_idle_with_hints (unsigned long eax,unsigned long ecx); +#define stack_current () \ ({ \ struct thread_info *ti; \
Signature · 1 line
1.4.3.rc2.g23bed-dirty
PATCH 8/28 ACPI: consolidate functions in acpi ec driver
In reply to Len BrownFrom: Lennart Poettering <[email protected]>
Unify the following functions:
acpi_ec_poll_read()
acpi_ec_poll_write()
acpi_ec_poll_query()
acpi_ec_intr_read()
acpi_ec_intr_write()
acpi_ec_intr_query()into:
acpi_ec_poll_transaction()
acpi_ec_intr_transaction()
These new functions take as arguments an ACPI EC command, a few bytes to write to the EC data register and a buffer for a few bytes to read from the EC data register. The old _read(), _write(), _query() are just special cases of these functions.
Then unified the code in acpi_ec_poll_transaction() and acpi_ec_intr_transaction() a little more. Both functions are now just wrappers around the new acpi_ec_transaction_unlocked() function. The latter contains the EC access logic, the two original function now just do their special way of locking and call the the new function for the actual work.
This saves a lot of very similar code. The primary reason for doing this, however, is that my driver for MSI 270 laptops needs to issue some non-standard EC commands in a safe way. Due to this I added a new exported function similar to ec_write()/ec_write() which is called ec_transaction() and is essentially just a wrapper around acpi_ec_{poll,intr}_transaction().
--- drivers/acpi/ec.c | 325 +++++++++++++++----------------------------------- include/linux/acpi.h | 3 + 2 files changed, 98 insertions(+), 230 deletions(-)
drivers/acpi/ec.c +95 -230
@@ -122,12 +122,12 @@ union acpi_ec {static int acpi_ec_poll_wait (union acpi_ec *ec,u8 event);static int acpi_ec_intr_wait (union acpi_ec *ec,unsigned int event); -static int acpi_ec_poll_read (union acpi_ec *ec,u8 address,u32 * data); -static int acpi_ec_intr_read (union acpi_ec *ec,u8 address,u32 * data); -static int acpi_ec_poll_write (union acpi_ec *ec,u8 address,u8 data); -static int acpi_ec_intr_write (union acpi_ec *ec,u8 address,u8 data); -static int acpi_ec_poll_query (union acpi_ec *ec,u32 * data); -static int acpi_ec_intr_query (union acpi_ec *ec,u32 * data); +static int acpi_ec_poll_transaction (union acpi_ec *ec,u8 command, +const u8 *wdata,unsigned wdata_len, +u8 *rdata,unsigned rdata_len); +static int acpi_ec_intr_transaction (union acpi_ec *ec,u8 command, +const u8 *wdata,unsigned wdata_len, +u8 *rdata,unsigned rdata_len);static void acpi_ec_gpe_poll_query (void *ec_cxt);static void acpi_ec_gpe_intr_query (void *ec_cxt);static u32 acpi_ec_gpe_poll_handler (void *data);
@@ -302,110 +302,95 @@ end: }#endif /* ACPI_FUTURE_USAGE */ -static int acpi_ec_read (union acpi_ec *ec,u8 address,u32 * data) +static int acpi_ec_transaction (union acpi_ec *ec,u8 command, +const u8 *wdata,unsigned wdata_len, +u8 *rdata,unsigned rdata_len) {if (acpi_ec_poll_mode) -return acpi_ec_poll_read (ec, address, data); +return acpi_ec_poll_transaction (ec, command, wdata, wdata_len, rdata, rdata_len);else -return acpi_ec_intr_read (ec, address, data); +return acpi_ec_intr_transaction (ec, command, wdata, wdata_len, rdata, rdata_len); +} +static int acpi_ec_read (union acpi_ec *ec,u8 address,u32 * data) +{ +int result; +u8 d; + result =acpi_ec_transaction (ec,ACPI_EC_COMMAND_READ , &address,1 , &d,1 ); + *data = d; +return result; }static int acpi_ec_write (union acpi_ec *ec,u8 address,u8 data) { -if (acpi_ec_poll_mode) -return acpi_ec_poll_write (ec, address, data); -else -return acpi_ec_intr_write (ec, address, data); +u8 wdata[2 ] = { address, data }; +return acpi_ec_transaction (ec,ACPI_EC_COMMAND_WRITE , wdata,2 ,NULL ,0 ); } -static int acpi_ec_poll_read (union acpi_ec *ec,u8 address,u32 * data) + +static int acpi_ec_transaction_unlocked (union acpi_ec *ec,u8 command, +const u8 *wdata,unsigned wdata_len, +u8 *rdata,unsigned rdata_len) { -acpi_status status =AE_OK ; -int result =0 ; -u32 glk =0 ; +int result; +acpi_hw_low_level_write (8 , command, &ec->common.command_addr); -if (!ec || !data) -return -EINVAL ; + result =acpi_ec_wait (ec,ACPI_EC_EVENT_IBE ); +if (result) +return result; - *data =0 ; +for (; wdata_len >0 ; wdata_len --) { -if (ec->common.global_lock) { - status =acpi_acquire_global_lock (ACPI_EC_UDELAY_GLK , &glk); -if (ACPI_FAILURE (status)) -return -ENODEV ; - } +acpi_hw_low_level_write (8 , *(wdata++), &ec->common.data_addr); -if (down_interruptible (&ec->poll.sem)) { - result = -ERESTARTSYS ; - goto end_nosem; - } - -acpi_hw_low_level_write (8 ,ACPI_EC_COMMAND_READ , - &ec->common.command_addr); - result =acpi_ec_wait (ec,ACPI_EC_EVENT_IBE ); -if (result) - goto end; + result =acpi_ec_wait (ec,ACPI_EC_EVENT_IBE ); +if (result) +return result; + } -acpi_hw_low_level_write (8 , address, &ec->common.data_addr); - result =acpi_ec_wait (ec,ACPI_EC_EVENT_OBF ); -if (result) - goto end; -acpi_hw_low_level_read (8 , data, &ec->common.data_addr); +for (; rdata_len >0 ; rdata_len --) { +u32 d; -ACPI_DEBUG_PRINT ((ACPI_DB_INFO ,"Read [%02x] from address [%02x]\n" , - *data, address)); + result =acpi_ec_wait (ec,ACPI_EC_EVENT_OBF ); +if (result) +return result; - end: -up (&ec->poll.sem); -end_nosem: -if (ec->common.global_lock) -acpi_release_global_lock (glk); +acpi_hw_low_level_read (8 , &d, &ec->common.data_addr); + *(rdata++) = (u8 ) d; + } -return result; +return 0 ; } -static int acpi_ec_poll_write (union acpi_ec *ec,u8 address,u8 data) +static int acpi_ec_poll_transaction (union acpi_ec *ec,u8 command, +const u8 *wdata,unsigned wdata_len, +u8 *rdata,unsigned rdata_len) { -int result =0 ;acpi_status status =AE_OK ; +int result;u32 glk =0 ; - -if (!ec) +if (!ec || (wdata_len && !wdata) || (rdata_len && !rdata))return -EINVAL ; +if (rdata) +memset (rdata,0 , rdata_len); +if (ec->common.global_lock) { status =acpi_acquire_global_lock (ACPI_EC_UDELAY_GLK , &glk);if (ACPI_FAILURE (status))return -ENODEV ; - } + }if (down_interruptible (&ec->poll.sem)) { result = -ERESTARTSYS ; goto end_nosem; } - -acpi_hw_low_level_write (8 ,ACPI_EC_COMMAND_WRITE , - &ec->common.command_addr); - result =acpi_ec_wait (ec,ACPI_EC_EVENT_IBE ); -if (result) - goto end; -acpi_hw_low_level_write (8 , address, &ec->common.data_addr); - result =acpi_ec_wait (ec,ACPI_EC_EVENT_IBE ); -if (result) - goto end; - -acpi_hw_low_level_write (8 , data, &ec->common.data_addr); - result =acpi_ec_wait (ec,ACPI_EC_EVENT_IBE ); -if (result) - goto end; - -ACPI_DEBUG_PRINT ((ACPI_DB_INFO ,"Wrote [%02x] to address [%02x]\n" , - data, address)); - - end: + result =acpi_ec_transaction_unlocked (ec, command, + wdata, wdata_len, + rdata, rdata_len);up (&ec->poll.sem); + end_nosem:if (ec->common.global_lock)acpi_release_global_lock (glk);
@@ -413,16 +398,18 @@ end_nosem:return result; } -static int acpi_ec_intr_read (union acpi_ec *ec,u8 address,u32 * data) +static int acpi_ec_intr_transaction (union acpi_ec *ec,u8 command, +const u8 *wdata,unsigned wdata_len, +u8 *rdata,unsigned rdata_len) { -int status =0 ; +int status;u32 glk; - -if (!ec || !data) +if (!ec || (wdata_len && !wdata) || (rdata_len && !rdata))return -EINVAL ; - *data =0 ; +if (rdata) +memset (rdata,0 , rdata_len);if (ec->common.global_lock) { status =acpi_acquire_global_lock (ACPI_EC_UDELAY_GLK , &glk);
@@ -438,72 +425,12 @@ static int acpi_ec_intr_read(union acpi_ printk(KERN_DEBUG PREFIX "read EC, IB not empty\n"); goto end; } -acpi_hw_low_level_write (8 ,ACPI_EC_COMMAND_READ , - &ec->common.command_addr); - status =acpi_ec_wait (ec,ACPI_EC_EVENT_IBE ); -if (status) { - printk(KERN_DEBUG PREFIX "read EC, IB not empty\n"); - } - -acpi_hw_low_level_write (8 , address, &ec->common.data_addr); - status =acpi_ec_wait (ec,ACPI_EC_EVENT_OBF ); -if (status) { - printk(KERN_DEBUG PREFIX "read EC, OB not full\n"); - goto end; - } -acpi_hw_low_level_read (8 , data, &ec->common.data_addr); -ACPI_DEBUG_PRINT ((ACPI_DB_INFO ,"Read [%02x] from address [%02x]\n" , - *data, address)); - - end: -up (&ec->intr.sem); - -if (ec->common.global_lock) -acpi_release_global_lock (glk); - -return status; -} - -static int acpi_ec_intr_write (union acpi_ec *ec,u8 address,u8 data) -{ -int status =0 ; -u32 glk; - - -if (!ec) -return -EINVAL ; - -if (ec->common.global_lock) { - status =acpi_acquire_global_lock (ACPI_EC_UDELAY_GLK , &glk); -if (ACPI_FAILURE (status)) -return -ENODEV ; - } - -WARN_ON (in_interrupt ()); -down (&ec->intr.sem); - - status =acpi_ec_wait (ec,ACPI_EC_EVENT_IBE ); -if (status) { - printk(KERN_DEBUG PREFIX "write EC, IB not empty\n"); - } -acpi_hw_low_level_write (8 ,ACPI_EC_COMMAND_WRITE , - &ec->common.command_addr); - status =acpi_ec_wait (ec,ACPI_EC_EVENT_IBE ); -if (status) { - printk(KERN_DEBUG PREFIX "write EC, IB not empty\n"); - } - -acpi_hw_low_level_write (8 , address, &ec->common.data_addr); - status =acpi_ec_wait (ec,ACPI_EC_EVENT_IBE ); -if (status) { - printk(KERN_DEBUG PREFIX "write EC, IB not empty\n"); - } -acpi_hw_low_level_write (8 , data, &ec->common.data_addr); - -ACPI_DEBUG_PRINT ((ACPI_DB_INFO ,"Wrote [%02x] to address [%02x]\n" , - data, address)); + status =acpi_ec_transaction_unlocked (ec, command, + wdata, wdata_len, + rdata, rdata_len); +end:up (&ec->intr.sem);if (ec->common.global_lock)
@@ -554,106 +481,44 @@ int ec_write(u8 addr, u8 val)EXPORT_SYMBOL (ec_write); -static int acpi_ec_query (union acpi_ec *ec,u32 * data) -{ -if (acpi_ec_poll_mode) -return acpi_ec_poll_query (ec, data); -else -return acpi_ec_intr_query (ec, data); -} -static int acpi_ec_poll_query (union acpi_ec *ec,u32 * data) +extern int ec_transaction (u8 command, +const u8 *wdata,unsigned wdata_len, +u8 *rdata,unsigned rdata_len) { -int result =0 ; -acpi_status status =AE_OK ; -u32 glk =0 ; - - -if (!ec || !data) -return -EINVAL ; - - *data =0 ; - -if (ec->common.global_lock) { - status =acpi_acquire_global_lock (ACPI_EC_UDELAY_GLK , &glk); -if (ACPI_FAILURE (status)) -return -ENODEV ; - } - -/* -* Query the EC to find out which _Qxx method we need to evaluate. -* Note that successful completion of the query causes the ACPI_EC_SCI -* bit to be cleared (and thus clearing the interrupt source). -*/ -if (down_interruptible (&ec->poll.sem)) { - result = -ERESTARTSYS ; - goto end_nosem; - } - -acpi_hw_low_level_write (8 ,ACPI_EC_COMMAND_QUERY , - &ec->common.command_addr); - result =acpi_ec_wait (ec,ACPI_EC_EVENT_OBF ); -if (result) - goto end; +union acpi_ec *ec; -acpi_hw_low_level_read (8 , data, &ec->common.data_addr); -if (!*data) - result = -ENODATA ; +if (!first_ec) +return -ENODEV ; - end: -up (&ec->poll.sem); -end_nosem: -if (ec->common.global_lock) -acpi_release_global_lock (glk); + ec =acpi_driver_data (first_ec); -return result; +return acpi_ec_transaction (ec, command, wdata, wdata_len, rdata, rdata_len); } -static int acpi_ec_intr_query (union acpi_ec *ec,u32 * data) -{ -int status =0 ; -u32 glk; +EXPORT_SYMBOL (ec_transaction); -if (!ec || !data) -return -EINVAL ; - *data =0 ; +static int acpi_ec_query (union acpi_ec *ec,u32 * data) { +int result; +u8 d; -if (ec->common.global_lock) { - status =acpi_acquire_global_lock (ACPI_EC_UDELAY_GLK , &glk); -if (ACPI_FAILURE (status)) -return -ENODEV ; - } +if (!ec || !data) +return -EINVAL ; -down (&ec->intr.sem); +/* +* Query the EC to find out which _Qxx method we need to evaluate. +* Note that successful completion of the query causes the ACPI_EC_SCI +* bit to be cleared (and thus clearing the interrupt source). +*/ - status =acpi_ec_wait (ec,ACPI_EC_EVENT_IBE ); -if (status) { - printk(KERN_DEBUG PREFIX "query EC, IB not empty\n"); - goto end; - } -/* -* Query the EC to find out which _Qxx method we need to evaluate. -* Note that successful completion of the query causes the ACPI_EC_SCI -* bit to be cleared (and thus clearing the interrupt source). -*/ -acpi_hw_low_level_write (8 ,ACPI_EC_COMMAND_QUERY , - &ec->common.command_addr); - status =acpi_ec_wait (ec,ACPI_EC_EVENT_OBF ); -if (status) { - printk(KERN_DEBUG PREFIX "query EC, OB not full\n"); - goto end; - } - -acpi_hw_low_level_read (8 , data, &ec->common.data_addr); -if (!*data) - status = -ENODATA ; + result =acpi_ec_transaction (ec,ACPI_EC_COMMAND_QUERY ,NULL ,0 , &d,1 ); +if (result) +return result; - end: -up (&ec->intr.sem); +if (!d) +return -ENODATA ; -if (ec->common.global_lock) -acpi_release_global_lock (glk); - -return status; + *data = d; +return 0 ; }/* --------------------------------------------------------------------------
include/linux/acpi.h +3 -0
@@ -494,6 +494,9 @@ #ifdef CONFIG_ACPI_ECextern int ec_read (u8 addr,u8 *val);extern int ec_write (u8 addr,u8 val); +extern int ec_transaction (u8 command, +const u8 *wdata,unsigned wdata_len, +u8 *rdata,unsigned rdata_len);#endif /*CONFIG_ACPI_EC*/
Signature · 1 line
1.4.3.rc2.g23bed-dirty
PATCH 14/28 ACPI: EC: export ec_transaction() for msi-laptop driver
In reply to Len BrownFrom: Lennart Poettering <[email protected]>
--- drivers/acpi/ec.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
drivers/acpi/ec.c +2 -0
@@ -384,6 +384,8 @@ extern int ec_transaction(u8 command, wdata_len, rdata, rdata_len); } +EXPORT_SYMBOL (ec_transaction); +static int acpi_ec_query (struct acpi_ec *ec,u8 *data) {int result;
Signature · 1 line
1.4.3.rc2.g23bed-dirty
PATCH 15/28 MSI S270 Laptop support: backlight, wlan, bluetooth states
In reply to Len BrownFrom: Lennart Poettering <[email protected]>
Create a driver to support the platform-specific features
of MSI S270 laptops (and maybe other MSI laptops).
This driver implements a backlight device for controlling LCD brightness (/sys/class/backlight/msi-laptop-bl/).
In addition it allows access to the WLAN and Bluetooth states through a platform driver (/sys/devices/platform/msi-laptop-pf/).
--- MAINTAINERS | 7 + drivers/misc/Kconfig | 19 +++ drivers/misc/Makefile | 1 + drivers/misc/msi-laptop.c | 395 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 422 insertions(+), 0 deletions(-)
MAINTAINERS +7 -0
@@ -1998,6 +1998,13 @@ M: [email protected] L: [email protected] S: Maintained +MSI LAPTOP SUPPORT +P: Lennart Poettering +M: [email protected] +L: https://tango.0pointer.de/mailman/listinfo/s270-linux +W: http://0pointer.de/lennart/tchibo.html +S: Maintained + MTRR AND SIMILAR SUPPORT [i386] P: Richard Gooch M: [email protected]
drivers/misc/Kconfig +19 -0
@@ -57,4 +57,23 @@ config TIFM_7XX1 To compile this driver as a module, choose M here: the module will be called tifm_7xx1. +config MSI_LAPTOP + tristate "MSI Laptop Extras" + depends on X86 + depends on ACPI_EC + depends on BACKLIGHT_CLASS_DEVICE + ---help--- + This is a driver for laptops built by MSI (MICRO-STAR + INTERNATIONAL): + + MSI MegaBook S270 (MS-1013) + Cytron/TCM/Medion/Tchibo MD96100/SAM2000 + + It adds support for Bluetooth, WLAN and LCD brightness control. + + More information about this driver is available at + <http://0pointer.de/lennart/tchibo.html>. + + If you have an MSI S270 laptop, say Y or M here. + endmenu
drivers/misc/Makefile +1 -0
@@ -5,6 +5,7 @@ obj- := misc.o # Dummy rule to force bui obj-$(CONFIG_IBM_ASM) += ibmasm/ obj-$(CONFIG_HDPU_FEATURES) += hdpuftrs/ +obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o obj-$(CONFIG_LKDTM) += lkdtm.o obj-$(CONFIG_TIFM_CORE) += tifm_core.o obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o
drivers/misc/msi-laptop.c new file +395 -0
395 lines not on this page · raw message
Signature · 1 line
1.4.3.rc2.g23bed-dirty
PATCH 18/28 ACPI: ibm_acpi: delete obsolete documentation
In reply to Len BrownFrom: Pavel Machek <[email protected]>
As this module is now part of the kernel tree, there is no need for instructions on how to download it and build an external module.
--- Documentation/ibm-acpi.txt | 35 +---------------------------------- 1 files changed, 1 insertions(+), 34 deletions(-)
Documentation/ibm-acpi.txt +1 -34
@@ -53,40 +53,7 @@ Installation If you are compiling this driver as included in the Linux kernel sources, simply enable the CONFIG_ACPI_IBM option (Power Management / -ACPI / IBM ThinkPad Laptop Extras). The rest of this section describes -how to install this driver when downloaded from the web site. - -First, you need to get a kernel with ACPI support up and running. -Please refer to http://acpi.sourceforge.net/ for help with this -step. How successful you will be depends a lot on you ThinkPad model, -the kernel you are using and any additional patches applied. The -kernel provided with your distribution may not be good enough. I -needed to compile a 2.6.7 kernel with the 20040715 ACPI patch to get -ACPI working reliably on my ThinkPad X40. Old ThinkPad models may not -be supported at all. - -Assuming you have the basic ACPI support working (e.g. you can see the -/proc/acpi directory), follow the following steps to install this -driver: - - - unpack the archive: - - tar xzvf ibm-acpi-x.y.tar.gz; cd ibm-acpi-x.y - - - compile the driver: - - make - - - install the module in your kernel modules directory: - - make install - - - load the module: - - modprobe ibm_acpi - -After loading the module, check the "dmesg" output for any error messages. - +ACPI / IBM ThinkPad Laptop Extras). Features --------
Signature · 1 line
1.4.3.rc2.g23bed-dirty
PATCH 19/28 ACPI: fix potential OOPS in power driver with CONFIG_ACPI_DEBUG
In reply to Len BrownFrom: Dmitry Torokhov <[email protected]>
device was set to null and used before set in a debug printk
--- drivers/acpi/power.c | 9 +++------ 1 files changed, 3 insertions(+), 6 deletions(-)
drivers/acpi/power.c +3 -6
@@ -216,10 +216,8 @@ static int acpi_power_off_device(acpi_ha {int result =0 ;acpi_status status =AE_OK ; -struct acpi_device *device =NULL ;struct acpi_power_resource *resource =NULL ; - result =acpi_power_get_context (handle, &resource);if (result)return result;
@@ -230,13 +228,13 @@ static int acpi_power_off_device(acpi_haif (resource->references) {ACPI_DEBUG_PRINT ((ACPI_DB_INFO ,"Resource [%s] is still in use, dereferencing\n" , - device->pnp.bus_id)); + resource->device->pnp.bus_id));return 0 ; }if (resource->state ==ACPI_POWER_RESOURCE_STATE_OFF ) {ACPI_DEBUG_PRINT ((ACPI_DB_INFO ,"Resource [%s] already off\n" , - device->pnp.bus_id)); + resource->device->pnp.bus_id));return 0 ; }
@@ -251,8 +249,7 @@ static int acpi_power_off_device(acpi_hareturn -ENOEXEC ;/* Update the power resource's _device_ power state */ - device = resource->device; - device->power.state =ACPI_STATE_D3 ; + resource->device->power.state =ACPI_STATE_D3 ;ACPI_DEBUG_PRINT ((ACPI_DB_INFO ,"Resource [%s] turned off\n" , resource->name));
Signature · 1 line
1.4.3.rc2.g23bed-dirty
PATCH 20/28 ACPI: acpi_pci_link_set() can allocate with either GFP_ATOMIC or GFP_KERNEL
In reply to Len BrownFrom: Jiri Kosina <[email protected]>
acpi_pci_link_set() allocates both with interrupts on and with interrupts off (resume-time), so check interrupts and decide on GFP_ATOMIC or GFP_KERNEL at run-time.
--- drivers/acpi/pci_link.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/acpi/pci_link.c +1 -1
@@ -307,7 +307,7 @@ static int acpi_pci_link_set(struct acpiif (!link || !irq)return -EINVAL ; - resource =kmalloc (sizeof (*resource) +1 ,GFP_ATOMIC ); + resource =kmalloc (sizeof (*resource) +1 ,irqs_disabled () ?GFP_ATOMIC :GFP_KERNEL );if (!resource)return -ENOMEM ;
Signature · 1 line
1.4.3.rc2.g23bed-dirty
PATCH 21/28 ACPI: update comments in motherboard.c
In reply to Len Brown--- drivers/acpi/motherboard.c | 6 ++++++ 1 files changed, 6 insertions(+), 0 deletions(-)
drivers/acpi/motherboard.c +6 -0
@@ -48,6 +48,12 @@ #define IS_RESERVED_ADDR(base, len) \* the io ports if they really know they can use it, while * still preventing hotplug PCI devices from using it. */ + +/* +* When CONFIG_PNP is enabled, pnp/system.c binds to PNP0C01 +* and PNP0C02, redundant with acpi_reserve_io_ranges(). +* But acpi_reserve_io_ranges() is necessary for !CONFIG_PNP. +*/ static acpi_status acpi_reserve_io_ranges (struct acpi_resource *res,void *data) {struct resource *requested_res =NULL ;
Signature · 1 line
1.4.3.rc2.g23bed-dirty
Re: [PATCH 21/28] ACPI: update comments in motherboard.c
Quoted 9 lines · Len Brown
drivers/acpi/motherboard.c +0
-0Quoted 1 line
+/*
+ * When
CONFIG_PNPis enabled,pnp/system.cbinds to PNP0C01
+ * and PNP0C02, redundant withacpi_reserve_io_ranges().
+ * Butacpi_reserve_io_ranges()is necessary for !CONFIG_PNP.
+ */
staticacpi_statusacpi_reserve_io_ranges(struct acpi_resource *res, void *data)
I don't understand this comment.
IMHO, we should make CONFIG_ACPI should select CONFIG_PNP and CONFIG_PNPACPI, move the FADT resource reservations somewhere else in ACPI, make pnp/system.c reserve all the resources (not just I/O ports), and remove acpi/motherboard.c.
Bjorn
PATCH 22/28 ACPI: fix section for CPU init functions
In reply to Len BrownFrom: Pierre Ossman <[email protected]>
The ACPI processor init functions should be marked as __cpuinit as they use structures marked with __cpuinitdata.
--- drivers/acpi/processor_core.c | 2 +- drivers/acpi/processor_idle.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/acpi/processor_core.c +1 -1
@@ -519,7 +519,7 @@ #endifstatic void *processor_device_array[NR_CPUS ]; -static int acpi_processor_start (struct acpi_device *device) +static int __cpuinit acpi_processor_start (struct acpi_device *device) {int result =0 ;acpi_status status =AE_OK ;
drivers/acpi/processor_idle.c +1 -1
@@ -1105,7 +1105,7 @@ static struct notifier_block acpi_proces .notifier_call = acpi_processor_latency_notify, }; -int acpi_processor_power_init (struct acpi_processor *pr, +int __cpuinit acpi_processor_power_init (struct acpi_processor *pr,struct acpi_device *device) {acpi_status status =0 ;
Signature · 1 line
1.4.3.rc2.g23bed-dirty
PATCH 23/28 ACPI: fix printk format warnings
In reply to Len BrownFrom: Randy Dunlap <[email protected]>
Fix printk format warnings in drivers/acpi:drivers/acpi/tables/tbget.c:326: warning: format '%X' expects type 'unsigned int', but argument 5 has type 'long unsigned int' drivers/acpi/tables/tbrsdt.c:189: warning: format '%X' expects type 'unsigned int', but argument 5 has type 'long unsigned int'
--- drivers/acpi/tables/tbget.c | 2 +- drivers/acpi/tables/tbrsdt.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/acpi/tables/tbget.c +1 -1
@@ -324,7 +324,7 @@ acpi_tb_get_this_table(struct acpi_pointif (header->length <sizeof (struct acpi_table_header )) {ACPI_ERROR ((AE_INFO , -"Table length (%X) is smaller than minimum (%X)" , +"Table length (%X) is smaller than minimum (%zX)" , header->length,sizeof (struct acpi_table_header )));return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH );
drivers/acpi/tables/tbrsdt.c +1 -1
@@ -187,7 +187,7 @@ acpi_status acpi_tb_validate_rsdt(structif (table_ptr->length <sizeof (struct acpi_table_header )) {ACPI_ERROR ((AE_INFO , -"RSDT/XSDT length (%X) is smaller than minimum (%X)" , +"RSDT/XSDT length (%X) is smaller than minimum (%zX)" , table_ptr->length,sizeof (struct acpi_table_header )));
Signature · 1 line
1.4.3.rc2.g23bed-dirty
PATCH 24/28 ACPI: SCI interrupt source override
In reply to Len BrownFrom: Kimball Murray <[email protected]>
The Linux group at Stratus Technologies has come across an issue with SCI routing under ACPI. We were bitten by this when we made an x86_64 platform whose BIOS provides an Interrupt Source Override for the SCI itself. Apparently the override has no effect for the System Control Interrupt, and this appears to be because of the way the SCI is setup in the ACPI code. It does not handle the case where busirq != gsi.
The code that sets up the SCI routing assumes that bus irq == global irq. So there is simply no provision for telling it otherwise. The attached patch provides this mechanism.
This patch provided by David Bulkow, was tested on an i386 platform, which does not use the SCI override, and also on an x86_64 platform which does use an override.
--- arch/i386/kernel/acpi/boot.c | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-)
arch/i386/kernel/acpi/boot.c +5 -5
@@ -332,7 +332,7 @@ acpi_parse_ioapic(acpi_table_entry_heade/* * Parse Interrupt Source Override for the ACPI SCI */ -static void acpi_sci_ioapic_setup (u32 gsi,u16 polarity,u16 trigger) +static void acpi_sci_ioapic_setup (u32 bus_irq,u32 gsi,u16 polarity,u16 trigger) {if (trigger ==0 )/* compatible SCI trigger is level */ trigger =3 ;
@@ -352,13 +352,13 @@ static void acpi_sci_ioapic_setup(u32 gs* If GSI is < 16, this will update its flags, * else it will create a new mp_irqs[] entry. */ -mp_override_legacy_irq (gsi, polarity, trigger, gsi); +mp_override_legacy_irq (bus_irq, polarity, trigger, gsi);/* * stash over-ride to indicate we've been here * and for later update of acpi_fadt */ - acpi_sci_override_gsi = gsi; + acpi_sci_override_gsi = bus_irq;return ; }
@@ -376,7 +376,7 @@ acpi_parse_int_src_ovr(acpi_table_entry_acpi_table_print_madt_entry (header);if (intsrc->bus_irq == acpi_fadt.sci_int) { -acpi_sci_ioapic_setup (intsrc->global_irq, +acpi_sci_ioapic_setup (intsrc->bus_irq, intsrc->global_irq, intsrc->flags.polarity, intsrc->flags.trigger);return 0 ;
@@ -879,7 +879,7 @@ static int __init acpi_parse_madt_ioapic* pretend we got one so we can set the SCI flags. */ if (!acpi_sci_override_gsi) -acpi_sci_ioapic_setup (acpi_fadt.sci_int,0 ,0 ); +acpi_sci_ioapic_setup (acpi_fadt.sci_int, acpi_fadt.sci_int,0 ,0 );/* Fill in identity legacy mapings where no override */ mp_config_acpi_legacy_irqs ();
Signature · 1 line
1.4.3.rc2.g23bed-dirty
PATCH 25/28 ACPI: asus_acpi: fix proc files parsing
In reply to Len BrownFrom: Darren Jenkins <[email protected]>
ICC complains about a "Pointless comparsion of unsigned interger with zero" @ line 760 & 808 of asus_acpi.c
parse_arg() mentioned below returns -E but it's copied into unsigned variable...
--- drivers/acpi/asus_acpi.c | 46 +++++++++++++++++++++++----------------------- 1 files changed, 23 insertions(+), 23 deletions(-)
drivers/acpi/asus_acpi.c +23 -23
@@ -567,11 +567,11 @@ static int write_led(const char __user * buffer, unsigned long count, char *ledname, int ledmask, int invert) { - int value; + int rv, value;int led_out =0 ; - count =parse_arg (buffer, count, &value); -if (count >0 ) + rv =parse_arg (buffer, count, &value); +if (rv >0 ) led_out = value ?1 :0 ; hotk->status =
@@ -584,7 +584,7 @@ write_led(const char __user * buffer, unprintk (KERN_WARNING "Asus ACPI: LED (%s) write failed\n" , ledname); -return count; +return rv; }/*
@@ -619,20 +619,20 @@ static int proc_write_ledd(struct file *file, const char __user * buffer, unsigned long count, void *data) { - int value; + int rv, value; - count =parse_arg (buffer, count, &value); -if (count >0 ) { + rv =parse_arg (buffer, count, &value); +if (rv >0 ) {if (!write_acpi_int (hotk->handle, hotk->methods->mt_ledd, value,NULL ))printk (KERN_WARNING "Asus ACPI: LED display write failed\n" );else hotk->ledd_status = (u32 ) value; - }else if (count <0 ) + }else if (rv <0 )printk (KERN_WARNING "Asus ACPI: Error reading user input\n" ); -return count; +return rv; }/*
@@ -773,12 +773,12 @@ static int proc_write_lcd(struct file *file, const char __user * buffer, unsigned long count, void *data) { - int value; + int rv, value; - count =parse_arg (buffer, count, &value); -if (count >0 ) + rv =parse_arg (buffer, count, &value); +if (rv >0 )set_lcd_state (value); -return count; +return rv; }static int read_brightness (void )
@@ -842,18 +842,18 @@ static int proc_write_brn(struct file *file, const char __user * buffer, unsigned long count, void *data) { - int value; + int rv, value; - count =parse_arg (buffer, count, &value); -if (count >0 ) { + rv =parse_arg (buffer, count, &value); +if (rv >0 ) { value = (0 < value) ? ((15 < value) ?15 : value) :0 ;/* 0 <= value <= 15 */ set_brightness (value); - }else if (count <0 ) { + }else if (rv <0 ) {printk (KERN_WARNING "Asus ACPI: Error reading user input\n" ); } -return count; +return rv; }static void set_display (int value)
@@ -892,15 +892,15 @@ static int proc_write_disp(struct file *file, const char __user * buffer, unsigned long count, void *data) { - int value; + int rv, value; - count =parse_arg (buffer, count, &value); -if (count >0 ) + rv =parse_arg (buffer, count, &value); +if (rv >0 )set_display (value); -else if (count <0 ) +else if (rv <0 )printk (KERN_WARNING "Asus ACPI: Error reading user input\n" ); -return count; +return rv; } typedef int (proc_readfunc) (char *page, char **start, off_t off, int count,
Signature · 1 line
1.4.3.rc2.g23bed-dirty
PATCH 26/28 ACPI: asus_acpi: don't printk on writing garbage to proc files
In reply to Len BrownFrom: Alexey Dobriyan <[email protected]>
This reporting is useless (we errno anyway).
--- drivers/acpi/asus_acpi.c | 10 +--------- 1 files changed, 1 insertions(+), 9 deletions(-)
drivers/acpi/asus_acpi.c +1 -9
@@ -629,9 +629,7 @@ proc_write_ledd(struct file *file, const "Asus ACPI: LED display write failed\n"); else hotk->ledd_status = (u32) value; - }else if (rv <0 ) -printk (KERN_WARNING "Asus ACPI: Error reading user input\n" ); - + }return rv; }
@@ -849,10 +847,7 @@ proc_write_brn(struct file *file, const value = (0 < value) ? ((15 < value) ?15 : value) :0 ;/* 0 <= value <= 15 */ set_brightness (value); - }else if (rv <0 ) { -printk (KERN_WARNING "Asus ACPI: Error reading user input\n" ); } -return rv; }
@@ -897,9 +892,6 @@ proc_write_disp(struct file *file, const rv =parse_arg (buffer, count, &value);if (rv >0 )set_display (value); -else if (rv <0 ) -printk (KERN_WARNING "Asus ACPI: Error reading user input\n" ); -return rv; }
Signature · 1 line
1.4.3.rc2.g23bed-dirty
PATCH 27/28 ACPICA: Fix incorrect handling of PCI Express Root Bridge _HID
In reply to Len BrownFrom: Eiichiro Oiwa <[email protected]>
I could not get correct PCI Express bus number from the structure of acpi_object_extra. I always get zero as bus number regardless of bus location. I found that there is incorrect comparison with _HID (PNP0A08) in acpi/events/evrgnini.c and PCI Express _BBN method always fail. Therefore, we always get zero as PCI Express bus number.
http://bugzilla.kernel.org/show_bug.cgi?id=7145
--- drivers/acpi/events/evrgnini.c | 13 ++++++------- 1 files changed, 6 insertions(+), 7 deletions(-)
drivers/acpi/events/evrgnini.c +6 -7
@@ -225,13 +225,12 @@ acpi_ev_pci_config_region_setup(acpi_hanif (! (ACPI_STRNCMP (object_hID.value,PCI_ROOT_HID_STRING , -sizeof (PCI_ROOT_HID_STRING )) - || - !(ACPI_STRNCMP - (object_hID.value, -PCI_EXPRESS_ROOT_HID_STRING , -sizeof (PCI_EXPRESS_ROOT_HID_STRING ))))) - { +sizeof (PCI_ROOT_HID_STRING ))) + || + !(ACPI_STRNCMP + (object_hID.value, +PCI_EXPRESS_ROOT_HID_STRING , +sizeof (PCI_EXPRESS_ROOT_HID_STRING )))) {/* Install a handler for this PCI root bridge */
Signature · 1 line
1.4.3.rc2.g23bed-dirty
PATCH 28/28 ACPI: check battery status on resume for un/plug events during sleep
In reply to Len BrownFrom: Jiri Kosina <[email protected]>
Add ->resume method to the ACPI battery handler to check if the battery state has changed during sleep. If yes, update the ACPI internal data structures for benefit of /proc/acpi/battery/.
--- drivers/acpi/battery.c | 14 ++++++++++++++ 1 files changed, 14 insertions(+), 0 deletions(-)
drivers/acpi/battery.c +14 -0
@@ -64,6 +64,7 @@ extern void *acpi_unlock_battery_dir(strstatic int acpi_battery_add (struct acpi_device *device);static int acpi_battery_remove (struct acpi_device *device,int type); +static int acpi_battery_resume (struct acpi_device *device,int status);static struct acpi_driver acpi_battery_driver = { .name =ACPI_BATTERY_DRIVER_NAME ,
@@ -71,6 +72,7 @@ static struct acpi_driver acpi_battery_d .ids = ACPI_BATTERY_HID, .ops = { .add = acpi_battery_add, + .resume = acpi_battery_resume, .remove = acpi_battery_remove, }, };
@@ -753,6 +755,18 @@ static int acpi_battery_remove(struct acreturn 0 ; } +/* this is needed to learn about changes made in suspended state */ +static int acpi_battery_resume (struct acpi_device *device,int state) +{ +struct acpi_battery *battery; + +if (!device) +return -EINVAL ; + + battery = device->driver_data; +return acpi_battery_check (battery); +} +static int __init acpi_battery_init (void ) {int result;
Signature · 1 line
1.4.3.rc2.g23bed-dirty