diff --git a/[refs] b/[refs] index fe59f7c43734..e5bf1acf5a9c 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 384bc8f07075804b9ce8807ed54dd7a483bd749a +refs/heads/master: 281ea49b0c294649a6de47a6f8fbe5611137726b diff --git a/trunk/Documentation/ibm-acpi.txt b/trunk/Documentation/ibm-acpi.txt index e50595bfd8ea..71aa40345272 100644 --- a/trunk/Documentation/ibm-acpi.txt +++ b/trunk/Documentation/ibm-acpi.txt @@ -30,10 +30,9 @@ detailed description): - ACPI sounds - temperature sensors - Experimental: embedded controller register dump - - LCD brightness control - - Volume control + - Experimental: LCD brightness control + - Experimental: 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 @@ -53,7 +52,40 @@ 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). +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. + Features -------- @@ -491,8 +523,13 @@ registers contain the current battery capacity, etc. If you experiment with this, do send me your results (including some complete dumps with a description of the conditions when they were taken.) -LCD brightness control -- /proc/acpi/ibm/brightness ---------------------------------------------------- +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. This feature allows software control of the LCD brightness on ThinkPad models which don't have a hardware brightness slider. The available @@ -505,8 +542,13 @@ commands are: The number range is 0 to 7, although not all of them may be distinct. The current brightness level is shown in the file. -Volume control -- /proc/acpi/ibm/volume ---------------------------------------- +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. This feature allows volume control on ThinkPad models which don't have a hardware volume knob. The available commands are: @@ -569,23 +611,6 @@ with the following command: echo '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 ------------------------------------ diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index a2b6d9fa3502..1b5430a49fdd 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -1998,13 +1998,6 @@ M: rubini@ipvvis.unipv.it L: linux-kernel@vger.kernel.org S: Maintained -MSI LAPTOP SUPPORT -P: Lennart Poettering -M: mzxreary@0pointer.de -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: rgooch@atnf.csiro.au diff --git a/trunk/arch/i386/kernel/acpi/boot.c b/trunk/arch/i386/kernel/acpi/boot.c index 92f79cdd9a48..ab974ff97073 100644 --- a/trunk/arch/i386/kernel/acpi/boot.c +++ b/trunk/arch/i386/kernel/acpi/boot.c @@ -332,7 +332,7 @@ acpi_parse_ioapic(acpi_table_entry_header * header, const unsigned long end) /* * 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 gsi, u16 polarity, u16 trigger) * 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_header * header, 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_entries(void) * 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(); diff --git a/trunk/arch/i386/kernel/acpi/cstate.c b/trunk/arch/i386/kernel/acpi/cstate.c index 20563e52c622..25db49ef1770 100644 --- a/trunk/arch/i386/kernel/acpi/cstate.c +++ b/trunk/arch/i386/kernel/acpi/cstate.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include @@ -42,124 +41,5 @@ void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags, 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); +EXPORT_SYMBOL(acpi_processor_power_init_bm_check); diff --git a/trunk/arch/i386/kernel/process.c b/trunk/arch/i386/kernel/process.c index 57d375900afb..b0a07801d9df 100644 --- a/trunk/arch/i386/kernel/process.c +++ b/trunk/arch/i386/kernel/process.c @@ -236,28 +236,20 @@ 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. */ -void mwait_idle_with_hints(unsigned long eax, unsigned long ecx) +static void mwait_idle(void) { - if (!need_resched()) { + local_irq_enable(); + + while (!need_resched()) { __monitor((void *)¤t_thread_info()->flags, 0, 0); smp_mb(); - if (!need_resched()) - __mwait(eax, ecx); + if (need_resched()) + break; + __mwait(0, 0); } } -/* 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)) { diff --git a/trunk/arch/x86_64/kernel/process.c b/trunk/arch/x86_64/kernel/process.c index 49f7fac6229e..5e95b257ee26 100644 --- a/trunk/arch/x86_64/kernel/process.c +++ b/trunk/arch/x86_64/kernel/process.c @@ -238,28 +238,20 @@ 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. */ -void mwait_idle_with_hints(unsigned long eax, unsigned long ecx) +static void mwait_idle(void) { - if (!need_resched()) { + local_irq_enable(); + + while (!need_resched()) { __monitor((void *)¤t_thread_info()->flags, 0, 0); smp_mb(); - if (!need_resched()) - __mwait(eax, ecx); + if (need_resched()) + break; + __mwait(0, 0); } } -/* 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; diff --git a/trunk/drivers/acpi/asus_acpi.c b/trunk/drivers/acpi/asus_acpi.c index c7ac9297a204..e9ee4c52a5f6 100644 --- a/trunk/drivers/acpi/asus_acpi.c +++ b/trunk/drivers/acpi/asus_acpi.c @@ -138,7 +138,6 @@ 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 @@ -377,17 +376,6 @@ static struct model_data model_conf[END_MODEL] = { .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 */ @@ -567,11 +555,11 @@ static int write_led(const char __user * buffer, unsigned long count, char *ledname, int ledmask, int invert) { - int rv, value; + int value; int led_out = 0; - rv = parse_arg(buffer, count, &value); - if (rv > 0) + count = parse_arg(buffer, count, &value); + if (count > 0) led_out = value ? 1 : 0; hotk->status = @@ -584,7 +572,7 @@ write_led(const char __user * buffer, unsigned long count, printk(KERN_WARNING "Asus ACPI: LED (%s) write failed\n", ledname); - return rv; + return count; } /* @@ -619,18 +607,20 @@ static int proc_write_ledd(struct file *file, const char __user * buffer, unsigned long count, void *data) { - int rv, value; + int value; - rv = parse_arg(buffer, count, &value); - if (rv > 0) { + count = parse_arg(buffer, count, &value); + if (count > 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; - } - return rv; + } else if (count < 0) + printk(KERN_WARNING "Asus ACPI: Error reading user input\n"); + + return count; } /* @@ -771,12 +761,12 @@ static int proc_write_lcd(struct file *file, const char __user * buffer, unsigned long count, void *data) { - int rv, value; + int value; - rv = parse_arg(buffer, count, &value); - if (rv > 0) + count = parse_arg(buffer, count, &value); + if (count > 0) set_lcd_state(value); - return rv; + return count; } static int read_brightness(void) @@ -840,15 +830,18 @@ static int proc_write_brn(struct file *file, const char __user * buffer, unsigned long count, void *data) { - int rv, value; + int value; - rv = parse_arg(buffer, count, &value); - if (rv > 0) { + count = parse_arg(buffer, count, &value); + if (count > 0) { value = (0 < value) ? ((15 < value) ? 15 : value) : 0; /* 0 <= value <= 15 */ set_brightness(value); + } else if (count < 0) { + printk(KERN_WARNING "Asus ACPI: Error reading user input\n"); } - return rv; + + return count; } static void set_display(int value) @@ -887,12 +880,15 @@ static int proc_write_disp(struct file *file, const char __user * buffer, unsigned long count, void *data) { - int rv, value; + int value; - rv = parse_arg(buffer, count, &value); - if (rv > 0) + count = parse_arg(buffer, count, &value); + if (count > 0) set_display(value); - return rv; + else if (count < 0) + printk(KERN_WARNING "Asus ACPI: Error reading user input\n"); + + return count; } typedef int (proc_readfunc) (char *page, char **start, off_t off, int count, @@ -1101,8 +1097,6 @@ 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 @@ -1206,10 +1200,9 @@ 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, S1N and W3V have a usable WLED */ + /* M2N and S1N have a usable WLED */ else if (asus_info) { if (strncmp(asus_info->oem_table_id, "L1", 2) == 0) hotk->methods->mled_status = NULL; diff --git a/trunk/drivers/acpi/battery.c b/trunk/drivers/acpi/battery.c index 026e40755cdd..9810e2a55d0a 100644 --- a/trunk/drivers/acpi/battery.c +++ b/trunk/drivers/acpi/battery.c @@ -64,7 +64,6 @@ extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); static 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, @@ -72,7 +71,6 @@ static struct acpi_driver acpi_battery_driver = { .ids = ACPI_BATTERY_HID, .ops = { .add = acpi_battery_add, - .resume = acpi_battery_resume, .remove = acpi_battery_remove, }, }; @@ -755,18 +753,6 @@ static int acpi_battery_remove(struct acpi_device *device, int type) return 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; diff --git a/trunk/drivers/acpi/ec.c b/trunk/drivers/acpi/ec.c index e6d4b084dca2..e5d796362854 100644 --- a/trunk/drivers/acpi/ec.c +++ b/trunk/drivers/acpi/ec.c @@ -45,143 +45,206 @@ ACPI_MODULE_NAME("acpi_ec") #define ACPI_EC_DRIVER_NAME "ACPI Embedded Controller Driver" #define ACPI_EC_DEVICE_NAME "Embedded Controller" #define ACPI_EC_FILE_INFO "info" - -/* EC status register */ #define ACPI_EC_FLAG_OBF 0x01 /* Output buffer full */ #define ACPI_EC_FLAG_IBF 0x02 /* Input buffer full */ #define ACPI_EC_FLAG_BURST 0x10 /* burst mode */ #define ACPI_EC_FLAG_SCI 0x20 /* EC-SCI occurred */ - -/* EC commands */ +#define ACPI_EC_EVENT_OBF 0x01 /* Output buffer full */ +#define ACPI_EC_EVENT_IBE 0x02 /* Input buffer empty */ +#define ACPI_EC_DELAY 50 /* Wait 50ms max. during EC ops */ +#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ +#define ACPI_EC_UDELAY 100 /* Poll @ 100us increments */ +#define ACPI_EC_UDELAY_COUNT 1000 /* Wait 10ms max. during EC ops */ #define ACPI_EC_COMMAND_READ 0x80 #define ACPI_EC_COMMAND_WRITE 0x81 #define ACPI_EC_BURST_ENABLE 0x82 #define ACPI_EC_BURST_DISABLE 0x83 #define ACPI_EC_COMMAND_QUERY 0x84 - -/* EC events */ -enum { - ACPI_EC_EVENT_OBF_1 = 1, /* Output buffer full */ - ACPI_EC_EVENT_IBF_0, /* Input buffer empty */ -}; - -#define ACPI_EC_DELAY 50 /* Wait 50ms max. during EC ops */ -#define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ -#define ACPI_EC_UDELAY 100 /* Poll @ 100us increments */ -#define ACPI_EC_UDELAY_COUNT 1000 /* Wait 10ms max. during EC ops */ - -enum { - EC_INTR = 1, /* Output buffer full */ - EC_POLL, /* Input buffer empty */ -}; - +#define EC_POLL 0xFF +#define EC_INTR 0x00 static int acpi_ec_remove(struct acpi_device *device, int type); static int acpi_ec_start(struct acpi_device *device); static int acpi_ec_stop(struct acpi_device *device, int type); -static int acpi_ec_add(struct acpi_device *device); +static int acpi_ec_intr_add(struct acpi_device *device); +static int acpi_ec_poll_add(struct acpi_device *device); static struct acpi_driver acpi_ec_driver = { .name = ACPI_EC_DRIVER_NAME, .class = ACPI_EC_CLASS, .ids = ACPI_EC_HID, .ops = { - .add = acpi_ec_add, + .add = acpi_ec_intr_add, .remove = acpi_ec_remove, .start = acpi_ec_start, .stop = acpi_ec_stop, }, }; +union acpi_ec { + struct { + u32 mode; + acpi_handle handle; + unsigned long uid; + unsigned long gpe_bit; + struct acpi_generic_address status_addr; + struct acpi_generic_address command_addr; + struct acpi_generic_address data_addr; + unsigned long global_lock; + } common; + + struct { + u32 mode; + acpi_handle handle; + unsigned long uid; + unsigned long gpe_bit; + struct acpi_generic_address status_addr; + struct acpi_generic_address command_addr; + struct acpi_generic_address data_addr; + unsigned long global_lock; + unsigned int expect_event; + atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */ + atomic_t pending_gpe; + struct semaphore sem; + wait_queue_head_t wait; + } intr; + + struct { + u32 mode; + acpi_handle handle; + unsigned long uid; + unsigned long gpe_bit; + struct acpi_generic_address status_addr; + struct acpi_generic_address command_addr; + struct acpi_generic_address data_addr; + unsigned long global_lock; + struct semaphore sem; + } poll; +}; +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 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); +static u32 acpi_ec_gpe_intr_handler(void *data); +static acpi_status __init +acpi_fake_ecdt_poll_callback(acpi_handle handle, + u32 Level, void *context, void **retval); + +static acpi_status __init +acpi_fake_ecdt_intr_callback(acpi_handle handle, + u32 Level, void *context, void **retval); + +static int __init acpi_ec_poll_get_real_ecdt(void); +static int __init acpi_ec_intr_get_real_ecdt(void); /* If we find an EC via the ECDT, we need to keep a ptr to its context */ -struct acpi_ec { - acpi_handle handle; - unsigned long uid; - unsigned long gpe_bit; - unsigned long command_addr; - unsigned long data_addr; - unsigned long global_lock; - struct semaphore sem; - unsigned int expect_event; - atomic_t leaving_burst; /* 0 : No, 1 : Yes, 2: abort */ - wait_queue_head_t wait; -} *ec_ecdt; +static union acpi_ec *ec_ecdt; /* External interfaces use first EC only, so remember */ static struct acpi_device *first_ec; -static int acpi_ec_mode = EC_INTR; +static int acpi_ec_poll_mode = EC_INTR; /* -------------------------------------------------------------------------- Transaction Management -------------------------------------------------------------------------- */ -static inline u8 acpi_ec_read_status(struct acpi_ec *ec) +static u32 acpi_ec_read_status(union acpi_ec *ec) { - return inb(ec->command_addr); -} + u32 status = 0; -static inline u8 acpi_ec_read_data(struct acpi_ec *ec) -{ - return inb(ec->data_addr); + acpi_hw_low_level_read(8, &status, &ec->common.status_addr); + return status; } -static inline void acpi_ec_write_cmd(struct acpi_ec *ec, u8 command) +static int acpi_ec_wait(union acpi_ec *ec, u8 event) { - outb(command, ec->command_addr); + if (acpi_ec_poll_mode) + return acpi_ec_poll_wait(ec, event); + else + return acpi_ec_intr_wait(ec, event); } -static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data) +static int acpi_ec_poll_wait(union acpi_ec *ec, u8 event) { - outb(data, ec->data_addr); -} + u32 acpi_ec_status = 0; + u32 i = ACPI_EC_UDELAY_COUNT; -static int acpi_ec_check_status(u8 status, u8 event) -{ + if (!ec) + return -EINVAL; + + /* Poll the EC status register waiting for the event to occur. */ switch (event) { - case ACPI_EC_EVENT_OBF_1: - if (status & ACPI_EC_FLAG_OBF) - return 1; + case ACPI_EC_EVENT_OBF: + do { + acpi_hw_low_level_read(8, &acpi_ec_status, + &ec->common.status_addr); + if (acpi_ec_status & ACPI_EC_FLAG_OBF) + return 0; + udelay(ACPI_EC_UDELAY); + } while (--i > 0); break; - case ACPI_EC_EVENT_IBF_0: - if (!(status & ACPI_EC_FLAG_IBF)) - return 1; + case ACPI_EC_EVENT_IBE: + do { + acpi_hw_low_level_read(8, &acpi_ec_status, + &ec->common.status_addr); + if (!(acpi_ec_status & ACPI_EC_FLAG_IBF)) + return 0; + udelay(ACPI_EC_UDELAY); + } while (--i > 0); break; default: - break; + return -EINVAL; } - return 0; + return -ETIME; } - -static int acpi_ec_wait(struct acpi_ec *ec, u8 event) +static int acpi_ec_intr_wait(union acpi_ec *ec, unsigned int event) { - int i = (acpi_ec_mode == EC_POLL) ? ACPI_EC_UDELAY_COUNT : 0; - long time_left; + int result = 0; - ec->expect_event = event; - if (acpi_ec_check_status(acpi_ec_read_status(ec), event)) { - ec->expect_event = 0; - return 0; + + ec->intr.expect_event = event; + smp_mb(); + + switch (event) { + case ACPI_EC_EVENT_IBE: + if (~acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) { + ec->intr.expect_event = 0; + return 0; + } + break; + default: + break; } - do { - if (acpi_ec_mode == EC_POLL) { - udelay(ACPI_EC_UDELAY); - } else { - time_left = wait_event_timeout(ec->wait, - !ec->expect_event, + result = wait_event_timeout(ec->intr.wait, + !ec->intr.expect_event, msecs_to_jiffies(ACPI_EC_DELAY)); - if (time_left > 0) { - ec->expect_event = 0; - return 0; - } - } - if (acpi_ec_check_status(acpi_ec_read_status(ec), event)) { - ec->expect_event = 0; + + ec->intr.expect_event = 0; + smp_mb(); + + /* + * Verify that the event in question has actually happened by + * querying EC status. Do the check even if operation timed-out + * to make sure that we did not miss interrupt. + */ + switch (event) { + case ACPI_EC_EVENT_OBF: + if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_OBF) return 0; - } - } while (--i > 0); + break; - ec->expect_event = 0; + case ACPI_EC_EVENT_IBE: + if (~acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) + return 0; + break; + } return -ETIME; } @@ -191,150 +254,272 @@ static int acpi_ec_wait(struct acpi_ec *ec, u8 event) * Note: samsung nv5000 doesn't work with ec burst mode. * http://bugzilla.kernel.org/show_bug.cgi?id=4980 */ -int acpi_ec_enter_burst_mode(struct acpi_ec *ec) +int acpi_ec_enter_burst_mode(union acpi_ec *ec) { - u8 tmp = 0; - u8 status = 0; + u32 tmp = 0; + int status = 0; status = acpi_ec_read_status(ec); if (status != -EINVAL && !(status & ACPI_EC_FLAG_BURST)) { - status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); + status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); if (status) goto end; - acpi_ec_write_cmd(ec, ACPI_EC_BURST_ENABLE); - status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1); - tmp = acpi_ec_read_data(ec); + acpi_hw_low_level_write(8, ACPI_EC_BURST_ENABLE, + &ec->common.command_addr); + status = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); + acpi_hw_low_level_read(8, &tmp, &ec->common.data_addr); if (tmp != 0x90) { /* Burst ACK byte */ return -EINVAL; } } - atomic_set(&ec->leaving_burst, 0); + atomic_set(&ec->intr.leaving_burst, 0); return 0; - end: - ACPI_EXCEPTION((AE_INFO, status, "EC wait, burst mode")); + end: + ACPI_EXCEPTION ((AE_INFO, status, "EC wait, burst mode"); return -1; } -int acpi_ec_leave_burst_mode(struct acpi_ec *ec) +int acpi_ec_leave_burst_mode(union acpi_ec *ec) { - u8 status = 0; + int status = 0; status = acpi_ec_read_status(ec); if (status != -EINVAL && (status & ACPI_EC_FLAG_BURST)){ - status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); + status = acpi_ec_wait(ec, ACPI_EC_FLAG_IBF); if(status) goto end; - acpi_ec_write_cmd(ec, ACPI_EC_BURST_DISABLE); - acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); - } - atomic_set(&ec->leaving_burst, 1); + acpi_hw_low_level_write(8, ACPI_EC_BURST_DISABLE, &ec->common.command_addr); + acpi_ec_wait(ec, ACPI_EC_FLAG_IBF); + } + atomic_set(&ec->intr.leaving_burst, 1); return 0; - end: - ACPI_EXCEPTION((AE_INFO, status, "EC leave burst mode")); +end: + ACPI_EXCEPTION((AE_INFO, status, "EC leave burst mode"); return -1; } #endif /* ACPI_FUTURE_USAGE */ -static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, - const u8 *wdata, unsigned wdata_len, - u8 *rdata, unsigned rdata_len) +static int acpi_ec_read(union acpi_ec *ec, u8 address, u32 * data) +{ + if (acpi_ec_poll_mode) + return acpi_ec_poll_read(ec, address, data); + else + return acpi_ec_intr_read(ec, address, data); +} +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); +} +static int acpi_ec_poll_read(union acpi_ec *ec, u8 address, u32 * data) { - int result; + acpi_status status = AE_OK; + int result = 0; + u32 glk = 0; - acpi_ec_write_cmd(ec, command); - for (; wdata_len > 0; wdata_len --) { - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); - if (result) - return result; - acpi_ec_write_data(ec, *(wdata++)); + 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; } - if (command == ACPI_EC_COMMAND_WRITE) { - result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); - if (result) - return result; + 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; + + 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); + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Read [%02x] from address [%02x]\n", + *data, address)); + + end: + up(&ec->poll.sem); +end_nosem: + if (ec->common.global_lock) + acpi_release_global_lock(glk); + + return result; +} + +static int acpi_ec_poll_write(union acpi_ec *ec, u8 address, u8 data) +{ + int result = 0; + acpi_status status = AE_OK; + u32 glk = 0; - for (; rdata_len > 0; rdata_len --) { - result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1); - if (result) - return result; - *(rdata++) = acpi_ec_read_data(ec); + 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; + } + + 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; - return 0; + 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: + up(&ec->poll.sem); +end_nosem: + if (ec->common.global_lock) + acpi_release_global_lock(glk); + + return result; } -static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, - const u8 *wdata, unsigned wdata_len, - u8 *rdata, unsigned rdata_len) +static int acpi_ec_intr_read(union acpi_ec *ec, u8 address, u32 * data) { - int status; + int status = 0; u32 glk; - if (!ec || (wdata_len && !wdata) || (rdata_len && !rdata)) + + if (!ec || !data) return -EINVAL; - if (rdata) - memset(rdata, 0, rdata_len); + *data = 0; - if (ec->global_lock) { + if (ec->common.global_lock) { status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); if (ACPI_FAILURE(status)) return -ENODEV; } - down(&ec->sem); - status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0); + WARN_ON(in_interrupt()); + down(&ec->intr.sem); + + status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); if (status) { 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"); + } - status = acpi_ec_transaction_unlocked(ec, command, - wdata, wdata_len, - rdata, rdata_len); + 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->sem); + end: + up(&ec->intr.sem); - if (ec->global_lock) + if (ec->common.global_lock) acpi_release_global_lock(glk); return status; } -static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 *data) +static int acpi_ec_intr_write(union acpi_ec *ec, u8 address, u8 data) { - int result; - u8 d; + int status = 0; + u32 glk; - result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_READ, - &address, 1, &d, 1); - *data = d; - return result; -} -static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data) -{ - u8 wdata[2] = { address, data }; - return acpi_ec_transaction(ec, ACPI_EC_COMMAND_WRITE, - wdata, 2, NULL, 0); + 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)); + + up(&ec->intr.sem); + + if (ec->common.global_lock) + acpi_release_global_lock(glk); + + return status; } /* * Externally callable EC access functions. For now, assume 1 EC only */ -int ec_read(u8 addr, u8 *val) +int ec_read(u8 addr, u8 * val) { - struct acpi_ec *ec; + union acpi_ec *ec; int err; - u8 temp_data; + u32 temp_data; if (!first_ec) return -ENODEV; @@ -354,7 +539,7 @@ EXPORT_SYMBOL(ec_read); int ec_write(u8 addr, u8 val) { - struct acpi_ec *ec; + union acpi_ec *ec; int err; if (!first_ec) @@ -369,106 +554,255 @@ int ec_write(u8 addr, u8 val) EXPORT_SYMBOL(ec_write); -extern int ec_transaction(u8 command, - const u8 *wdata, unsigned wdata_len, - u8 *rdata, unsigned rdata_len) +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) { - struct acpi_ec *ec; + int result = 0; + acpi_status status = AE_OK; + u32 glk = 0; - if (!first_ec) - return -ENODEV; - ec = acpi_driver_data(first_ec); + if (!ec || !data) + return -EINVAL; - return acpi_ec_transaction(ec, command, wdata, - wdata_len, rdata, rdata_len); -} + *data = 0; + + if (ec->common.global_lock) { + status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); + if (ACPI_FAILURE(status)) + return -ENODEV; + } -EXPORT_SYMBOL(ec_transaction); + /* + * 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; + + acpi_hw_low_level_read(8, data, &ec->common.data_addr); + if (!*data) + result = -ENODATA; + + end: + up(&ec->poll.sem); +end_nosem: + if (ec->common.global_lock) + acpi_release_global_lock(glk); -static int acpi_ec_query(struct acpi_ec *ec, u8 *data) + return result; +} +static int acpi_ec_intr_query(union acpi_ec *ec, u32 * data) { - int result; - u8 d; + int status = 0; + u32 glk; + + + 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; + } - 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; + } - result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_QUERY, NULL, 0, &d, 1); - if (result) - return result; + acpi_hw_low_level_read(8, data, &ec->common.data_addr); + if (!*data) + status = -ENODATA; - if (!d) - return -ENODATA; + end: + up(&ec->intr.sem); + + if (ec->common.global_lock) + acpi_release_global_lock(glk); - *data = d; - return 0; + return status; } /* -------------------------------------------------------------------------- Event Management -------------------------------------------------------------------------- */ -struct acpi_ec_query_data { +union acpi_ec_query_data { acpi_handle handle; u8 data; }; static void acpi_ec_gpe_query(void *ec_cxt) { - struct acpi_ec *ec = (struct acpi_ec *)ec_cxt; - u8 value = 0; - static char object_name[8]; + if (acpi_ec_poll_mode) + acpi_ec_gpe_poll_query(ec_cxt); + else + acpi_ec_gpe_intr_query(ec_cxt); +} - if (!ec) - goto end; +static void acpi_ec_gpe_poll_query(void *ec_cxt) +{ + union acpi_ec *ec = (union acpi_ec *)ec_cxt; + u32 value = 0; + static char object_name[5] = { '_', 'Q', '0', '0', '\0' }; + const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' + }; - value = acpi_ec_read_status(ec); + if (!ec_cxt) + goto end; + + if (down_interruptible (&ec->poll.sem)) { + return; + } + acpi_hw_low_level_read(8, &value, &ec->common.command_addr); + up(&ec->poll.sem); + + /* TBD: Implement asynch events! + * NOTE: All we care about are EC-SCI's. Other EC events are + * handled via polling (yuck!). This is because some systems + * treat EC-SCIs as level (versus EDGE!) triggered, preventing + * a purely interrupt-driven approach (grumble, grumble). + */ if (!(value & ACPI_EC_FLAG_SCI)) goto end; if (acpi_ec_query(ec, &value)) goto end; - snprintf(object_name, 8, "_Q%2.2X", value); + object_name[2] = hex[((value >> 4) & 0x0F)]; + object_name[3] = hex[(value & 0x0F)]; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name)); - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s", object_name)); + acpi_evaluate_object(ec->common.handle, object_name, NULL, NULL); - acpi_evaluate_object(ec->handle, object_name, NULL, NULL); + end: + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); +} +static void acpi_ec_gpe_intr_query(void *ec_cxt) +{ + union acpi_ec *ec = (union acpi_ec *)ec_cxt; + u32 value; + int result = -ENODATA; + static char object_name[5] = { '_', 'Q', '0', '0', '\0' }; + const char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' + }; + + if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_SCI) + result = acpi_ec_query(ec, &value); + + if (result) + goto end; + + object_name[2] = hex[((value >> 4) & 0x0F)]; + object_name[3] = hex[(value & 0x0F)]; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Evaluating %s\n", object_name)); + + acpi_evaluate_object(ec->common.handle, object_name, NULL, NULL); end: - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + atomic_dec(&ec->intr.pending_gpe); + return; } static u32 acpi_ec_gpe_handler(void *data) +{ + if (acpi_ec_poll_mode) + return acpi_ec_gpe_poll_handler(data); + else + return acpi_ec_gpe_intr_handler(data); +} +static u32 acpi_ec_gpe_poll_handler(void *data) { acpi_status status = AE_OK; - u8 value; - struct acpi_ec *ec = (struct acpi_ec *)data; + union acpi_ec *ec = (union acpi_ec *)data; + + if (!ec) + return ACPI_INTERRUPT_NOT_HANDLED; + + acpi_disable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); + + status = acpi_os_execute(OSL_EC_POLL_HANDLER, acpi_ec_gpe_query, ec); + + if (status == AE_OK) + return ACPI_INTERRUPT_HANDLED; + else + return ACPI_INTERRUPT_NOT_HANDLED; +} +static u32 acpi_ec_gpe_intr_handler(void *data) +{ + acpi_status status = AE_OK; + u32 value; + union acpi_ec *ec = (union acpi_ec *)data; + + if (!ec) + return ACPI_INTERRUPT_NOT_HANDLED; - acpi_clear_gpe(NULL, ec->gpe_bit, ACPI_ISR); + acpi_clear_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); value = acpi_ec_read_status(ec); - if (acpi_ec_mode == EC_INTR) { - if (acpi_ec_check_status(value, ec->expect_event)) { - ec->expect_event = 0; - wake_up(&ec->wait); - } + switch (ec->intr.expect_event) { + case ACPI_EC_EVENT_OBF: + if (!(value & ACPI_EC_FLAG_OBF)) + break; + ec->intr.expect_event = 0; + wake_up(&ec->intr.wait); + break; + case ACPI_EC_EVENT_IBE: + if ((value & ACPI_EC_FLAG_IBF)) + break; + ec->intr.expect_event = 0; + wake_up(&ec->intr.wait); + break; + default: + break; } if (value & ACPI_EC_FLAG_SCI) { - status = acpi_os_execute(OSL_EC_BURST_HANDLER, acpi_ec_gpe_query, ec); + atomic_add(1, &ec->intr.pending_gpe); + status = acpi_os_execute(OSL_EC_BURST_HANDLER, + acpi_ec_gpe_query, ec); return status == AE_OK ? ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; } - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_ISR); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_ISR); return status == AE_OK ? ACPI_INTERRUPT_HANDLED : ACPI_INTERRUPT_NOT_HANDLED; } @@ -499,7 +833,7 @@ acpi_ec_space_handler(u32 function, void *handler_context, void *region_context) { int result = 0; - struct acpi_ec *ec = NULL; + union acpi_ec *ec = NULL; u64 temp = *value; acpi_integer f_v = 0; int i = 0; @@ -509,16 +843,18 @@ acpi_ec_space_handler(u32 function, return AE_BAD_PARAMETER; if (bit_width != 8 && acpi_strict) { + printk(KERN_WARNING PREFIX + "acpi_ec_space_handler: bit_width should be 8\n"); return AE_BAD_PARAMETER; } - ec = (struct acpi_ec *)handler_context; + ec = (union acpi_ec *)handler_context; next_byte: switch (function) { case ACPI_READ: temp = 0; - result = acpi_ec_read(ec, (u8) address, (u8 *) &temp); + result = acpi_ec_read(ec, (u8) address, (u32 *) & temp); break; case ACPI_WRITE: result = acpi_ec_write(ec, (u8) address, (u8) temp); @@ -569,20 +905,20 @@ static struct proc_dir_entry *acpi_ec_dir; static int acpi_ec_read_info(struct seq_file *seq, void *offset) { - struct acpi_ec *ec = (struct acpi_ec *)seq->private; + union acpi_ec *ec = (union acpi_ec *)seq->private; if (!ec) goto end; seq_printf(seq, "gpe bit: 0x%02x\n", - (u32) ec->gpe_bit); + (u32) ec->common.gpe_bit); seq_printf(seq, "ports: 0x%02x, 0x%02x\n", - (u32) ec->command_addr, - (u32) ec->data_addr); + (u32) ec->common.status_addr.address, + (u32) ec->common.data_addr.address); seq_printf(seq, "use global lock: %s\n", - ec->global_lock ? "yes" : "no"); - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + ec->common.global_lock ? "yes" : "no"); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); end: return 0; @@ -593,7 +929,7 @@ static int acpi_ec_info_open_fs(struct inode *inode, struct file *file) return single_open(file, acpi_ec_read_info, PDE(inode)->data); } -static struct file_operations acpi_ec_info_ops = { +static const struct file_operations acpi_ec_info_ops = { .open = acpi_ec_info_open_fs, .read = seq_read, .llseek = seq_lseek, @@ -642,35 +978,101 @@ static int acpi_ec_remove_fs(struct acpi_device *device) Driver Interface -------------------------------------------------------------------------- */ -static int acpi_ec_add(struct acpi_device *device) +static int acpi_ec_poll_add(struct acpi_device *device) { int result = 0; acpi_status status = AE_OK; - struct acpi_ec *ec = NULL; + union acpi_ec *ec = NULL; if (!device) return -EINVAL; - ec = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); + ec = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); if (!ec) return -ENOMEM; - memset(ec, 0, sizeof(struct acpi_ec)); - - ec->handle = device->handle; - ec->uid = -1; - init_MUTEX(&ec->sem); - if (acpi_ec_mode == EC_INTR) { - atomic_set(&ec->leaving_burst, 1); - init_waitqueue_head(&ec->wait); + memset(ec, 0, sizeof(union acpi_ec)); + + ec->common.handle = device->handle; + ec->common.uid = -1; + init_MUTEX(&ec->poll.sem); + strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); + strcpy(acpi_device_class(device), ACPI_EC_CLASS); + acpi_driver_data(device) = ec; + + /* Use the global lock for all EC transactions? */ + acpi_evaluate_integer(ec->common.handle, "_GLK", NULL, + &ec->common.global_lock); + + /* XXX we don't test uids, because on some boxes ecdt uid = 0, see: + http://bugzilla.kernel.org/show_bug.cgi?id=6111 */ + if (ec_ecdt) { + acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, + ACPI_ADR_SPACE_EC, + &acpi_ec_space_handler); + + acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit, + &acpi_ec_gpe_handler); + + kfree(ec_ecdt); } + + /* Get GPE bit assignment (EC events). */ + /* TODO: Add support for _GPE returning a package */ + status = + acpi_evaluate_integer(ec->common.handle, "_GPE", NULL, + &ec->common.gpe_bit); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "Obtaining GPE bit")); + result = -ENODEV; + goto end; + } + + result = acpi_ec_add_fs(device); + if (result) + goto end; + + printk(KERN_INFO PREFIX "%s [%s] (gpe %d) polling mode.\n", + acpi_device_name(device), acpi_device_bid(device), + (u32) ec->common.gpe_bit); + + if (!first_ec) + first_ec = device; + + end: + if (result) + kfree(ec); + + return result; +} +static int acpi_ec_intr_add(struct acpi_device *device) +{ + int result = 0; + acpi_status status = AE_OK; + union acpi_ec *ec = NULL; + + + if (!device) + return -EINVAL; + + ec = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); + if (!ec) + return -ENOMEM; + memset(ec, 0, sizeof(union acpi_ec)); + + ec->common.handle = device->handle; + ec->common.uid = -1; + atomic_set(&ec->intr.pending_gpe, 0); + atomic_set(&ec->intr.leaving_burst, 1); + init_MUTEX(&ec->intr.sem); + init_waitqueue_head(&ec->intr.wait); strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_EC_CLASS); acpi_driver_data(device) = ec; /* Use the global lock for all EC transactions? */ - acpi_evaluate_integer(ec->handle, "_GLK", NULL, - &ec->global_lock); + acpi_evaluate_integer(ec->common.handle, "_GLK", NULL, + &ec->common.global_lock); /* XXX we don't test uids, because on some boxes ecdt uid = 0, see: http://bugzilla.kernel.org/show_bug.cgi?id=6111 */ @@ -679,7 +1081,7 @@ static int acpi_ec_add(struct acpi_device *device) ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); - acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit, + acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit, &acpi_ec_gpe_handler); kfree(ec_ecdt); @@ -688,10 +1090,10 @@ static int acpi_ec_add(struct acpi_device *device) /* Get GPE bit assignment (EC events). */ /* TODO: Add support for _GPE returning a package */ status = - acpi_evaluate_integer(ec->handle, "_GPE", NULL, - &ec->gpe_bit); + acpi_evaluate_integer(ec->common.handle, "_GPE", NULL, + &ec->common.gpe_bit); if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Obtaining GPE bit assignment")); + printk(KERN_ERR PREFIX "Obtaining GPE bit assignment\n"); result = -ENODEV; goto end; } @@ -700,14 +1102,14 @@ static int acpi_ec_add(struct acpi_device *device) if (result) goto end; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s [%s] (gpe %d) interrupt mode.", + printk(KERN_INFO PREFIX "%s [%s] (gpe %d) interrupt mode.\n", acpi_device_name(device), acpi_device_bid(device), - (u32) ec->gpe_bit)); + (u32) ec->common.gpe_bit); if (!first_ec) first_ec = device; - end: + end: if (result) kfree(ec); @@ -716,7 +1118,7 @@ static int acpi_ec_add(struct acpi_device *device) static int acpi_ec_remove(struct acpi_device *device, int type) { - struct acpi_ec *ec = NULL; + union acpi_ec *ec = NULL; if (!device) @@ -734,7 +1136,8 @@ static int acpi_ec_remove(struct acpi_device *device, int type) static acpi_status acpi_ec_io_ports(struct acpi_resource *resource, void *context) { - struct acpi_ec *ec = (struct acpi_ec *)context; + union acpi_ec *ec = (union acpi_ec *)context; + struct acpi_generic_address *addr; if (resource->type != ACPI_RESOURCE_TYPE_IO) { return AE_OK; @@ -745,21 +1148,26 @@ acpi_ec_io_ports(struct acpi_resource *resource, void *context) * the second address region returned is the status/command * port. */ - if (ec->data_addr == 0) { - ec->data_addr = resource->data.io.minimum; - } else if (ec->command_addr == 0) { - ec->command_addr = resource->data.io.minimum; + if (ec->common.data_addr.register_bit_width == 0) { + addr = &ec->common.data_addr; + } else if (ec->common.command_addr.register_bit_width == 0) { + addr = &ec->common.command_addr; } else { return AE_CTRL_TERMINATE; } + addr->address_space_id = ACPI_ADR_SPACE_SYSTEM_IO; + addr->register_bit_width = 8; + addr->register_bit_offset = 0; + addr->address = resource->data.io.minimum; + return AE_OK; } static int acpi_ec_start(struct acpi_device *device) { acpi_status status = AE_OK; - struct acpi_ec *ec = NULL; + union acpi_ec *ec = NULL; if (!device) @@ -773,35 +1181,39 @@ static int acpi_ec_start(struct acpi_device *device) /* * Get I/O port addresses. Convert to GAS format. */ - status = acpi_walk_resources(ec->handle, METHOD_NAME__CRS, + status = acpi_walk_resources(ec->common.handle, METHOD_NAME__CRS, acpi_ec_io_ports, ec); - if (ACPI_FAILURE(status) || ec->command_addr == 0) { - ACPI_EXCEPTION((AE_INFO, status, - "Error getting I/O port addresses")); + if (ACPI_FAILURE(status) + || ec->common.command_addr.register_bit_width == 0) { + printk(KERN_ERR PREFIX "Error getting I/O port addresses\n"); return -ENODEV; } - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02lx, ports=0x%2lx,0x%2lx", - ec->gpe_bit, ec->command_addr, ec->data_addr)); + ec->common.status_addr = ec->common.command_addr; + + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "gpe=0x%02x, ports=0x%2x,0x%2x\n", + (u32) ec->common.gpe_bit, + (u32) ec->common.command_addr.address, + (u32) ec->common.data_addr.address)); /* * Install GPE handler */ - status = acpi_install_gpe_handler(NULL, ec->gpe_bit, + status = acpi_install_gpe_handler(NULL, ec->common.gpe_bit, ACPI_GPE_EDGE_TRIGGERED, &acpi_ec_gpe_handler, ec); if (ACPI_FAILURE(status)) { return -ENODEV; } - acpi_set_gpe_type(NULL, ec->gpe_bit, ACPI_GPE_TYPE_RUNTIME); - acpi_enable_gpe(NULL, ec->gpe_bit, ACPI_NOT_ISR); + acpi_set_gpe_type(NULL, ec->common.gpe_bit, ACPI_GPE_TYPE_RUNTIME); + acpi_enable_gpe(NULL, ec->common.gpe_bit, ACPI_NOT_ISR); - status = acpi_install_address_space_handler(ec->handle, + status = acpi_install_address_space_handler(ec->common.handle, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler, &acpi_ec_space_setup, ec); if (ACPI_FAILURE(status)) { - acpi_remove_gpe_handler(NULL, ec->gpe_bit, + acpi_remove_gpe_handler(NULL, ec->common.gpe_bit, &acpi_ec_gpe_handler); return -ENODEV; } @@ -812,7 +1224,7 @@ static int acpi_ec_start(struct acpi_device *device) static int acpi_ec_stop(struct acpi_device *device, int type) { acpi_status status = AE_OK; - struct acpi_ec *ec = NULL; + union acpi_ec *ec = NULL; if (!device) @@ -820,14 +1232,14 @@ static int acpi_ec_stop(struct acpi_device *device, int type) ec = acpi_driver_data(device); - status = acpi_remove_address_space_handler(ec->handle, + status = acpi_remove_address_space_handler(ec->common.handle, ACPI_ADR_SPACE_EC, &acpi_ec_space_handler); if (ACPI_FAILURE(status)) return -ENODEV; status = - acpi_remove_gpe_handler(NULL, ec->gpe_bit, + acpi_remove_gpe_handler(NULL, ec->common.gpe_bit, &acpi_ec_gpe_handler); if (ACPI_FAILURE(status)) return -ENODEV; @@ -839,30 +1251,76 @@ static acpi_status __init acpi_fake_ecdt_callback(acpi_handle handle, u32 Level, void *context, void **retval) { + + if (acpi_ec_poll_mode) + return acpi_fake_ecdt_poll_callback(handle, + Level, context, retval); + else + return acpi_fake_ecdt_intr_callback(handle, + Level, context, retval); +} + +static acpi_status __init +acpi_fake_ecdt_poll_callback(acpi_handle handle, + u32 Level, void *context, void **retval) +{ acpi_status status; - init_MUTEX(&ec_ecdt->sem); - if (acpi_ec_mode == EC_INTR) { - init_waitqueue_head(&ec_ecdt->wait); - } status = acpi_walk_resources(handle, METHOD_NAME__CRS, acpi_ec_io_ports, ec_ecdt); if (ACPI_FAILURE(status)) return status; + ec_ecdt->common.status_addr = ec_ecdt->common.command_addr; + + ec_ecdt->common.uid = -1; + acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->common.uid); + + status = + acpi_evaluate_integer(handle, "_GPE", NULL, + &ec_ecdt->common.gpe_bit); + if (ACPI_FAILURE(status)) + return status; + init_MUTEX(&ec_ecdt->poll.sem); + ec_ecdt->common.global_lock = TRUE; + ec_ecdt->common.handle = handle; + + printk(KERN_INFO PREFIX "GPE=0x%02x, ports=0x%2x, 0x%2x\n", + (u32) ec_ecdt->common.gpe_bit, + (u32) ec_ecdt->common.command_addr.address, + (u32) ec_ecdt->common.data_addr.address); + + return AE_CTRL_TERMINATE; +} + +static acpi_status __init +acpi_fake_ecdt_intr_callback(acpi_handle handle, + u32 Level, void *context, void **retval) +{ + acpi_status status; + + init_MUTEX(&ec_ecdt->intr.sem); + init_waitqueue_head(&ec_ecdt->intr.wait); + status = acpi_walk_resources(handle, METHOD_NAME__CRS, + acpi_ec_io_ports, ec_ecdt); + if (ACPI_FAILURE(status)) + return status; + ec_ecdt->common.status_addr = ec_ecdt->common.command_addr; - ec_ecdt->uid = -1; - acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->uid); + ec_ecdt->common.uid = -1; + acpi_evaluate_integer(handle, "_UID", NULL, &ec_ecdt->common.uid); status = acpi_evaluate_integer(handle, "_GPE", NULL, - &ec_ecdt->gpe_bit); + &ec_ecdt->common.gpe_bit); if (ACPI_FAILURE(status)) return status; - ec_ecdt->global_lock = TRUE; - ec_ecdt->handle = handle; + ec_ecdt->common.global_lock = TRUE; + ec_ecdt->common.handle = handle; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "GPE=0x%02lx, ports=0x%2lx, 0x%2lx", - ec_ecdt->gpe_bit, ec_ecdt->command_addr, ec_ecdt->data_addr)); + printk(KERN_INFO PREFIX "GPE=0x%02x, ports=0x%2x, 0x%2x\n", + (u32) ec_ecdt->common.gpe_bit, + (u32) ec_ecdt->common.command_addr.address, + (u32) ec_ecdt->common.data_addr.address); return AE_CTRL_TERMINATE; } @@ -882,14 +1340,14 @@ static int __init acpi_ec_fake_ecdt(void) acpi_status status; int ret = 0; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Try to make an fake ECDT")); + printk(KERN_INFO PREFIX "Try to make an fake ECDT\n"); - ec_ecdt = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); + ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); if (!ec_ecdt) { ret = -ENOMEM; goto error; } - memset(ec_ecdt, 0, sizeof(struct acpi_ec)); + memset(ec_ecdt, 0, sizeof(union acpi_ec)); status = acpi_get_devices(ACPI_EC_HID, acpi_fake_ecdt_callback, NULL, NULL); @@ -897,15 +1355,23 @@ static int __init acpi_ec_fake_ecdt(void) kfree(ec_ecdt); ec_ecdt = NULL; ret = -ENODEV; - ACPI_EXCEPTION((AE_INFO, status, "Can't make an fake ECDT")); goto error; } return 0; - error: + error: + printk(KERN_ERR PREFIX "Can't make an fake ECDT\n"); return ret; } static int __init acpi_ec_get_real_ecdt(void) +{ + if (acpi_ec_poll_mode) + return acpi_ec_poll_get_real_ecdt(); + else + return acpi_ec_intr_get_real_ecdt(); +} + +static int __init acpi_ec_poll_get_real_ecdt(void) { acpi_status status; struct acpi_table_ecdt *ecdt_ptr; @@ -916,36 +1382,80 @@ static int __init acpi_ec_get_real_ecdt(void) if (ACPI_FAILURE(status)) return -ENODEV; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found ECDT")); + printk(KERN_INFO PREFIX "Found ECDT\n"); /* * Generate a temporary ec context to use until the namespace is scanned */ - ec_ecdt = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); + ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); if (!ec_ecdt) return -ENOMEM; - memset(ec_ecdt, 0, sizeof(struct acpi_ec)); + memset(ec_ecdt, 0, sizeof(union acpi_ec)); + + ec_ecdt->common.command_addr = ecdt_ptr->ec_control; + ec_ecdt->common.status_addr = ecdt_ptr->ec_control; + ec_ecdt->common.data_addr = ecdt_ptr->ec_data; + ec_ecdt->common.gpe_bit = ecdt_ptr->gpe_bit; + init_MUTEX(&ec_ecdt->poll.sem); + /* use the GL just to be safe */ + ec_ecdt->common.global_lock = TRUE; + ec_ecdt->common.uid = ecdt_ptr->uid; - init_MUTEX(&ec_ecdt->sem); - if (acpi_ec_mode == EC_INTR) { - init_waitqueue_head(&ec_ecdt->wait); + status = + acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->common.handle); + if (ACPI_FAILURE(status)) { + goto error; } - ec_ecdt->command_addr = ecdt_ptr->ec_control.address; - ec_ecdt->data_addr = ecdt_ptr->ec_data.address; - ec_ecdt->gpe_bit = ecdt_ptr->gpe_bit; + + return 0; + error: + printk(KERN_ERR PREFIX "Could not use ECDT\n"); + kfree(ec_ecdt); + ec_ecdt = NULL; + + return -ENODEV; +} + +static int __init acpi_ec_intr_get_real_ecdt(void) +{ + acpi_status status; + struct acpi_table_ecdt *ecdt_ptr; + + status = acpi_get_firmware_table("ECDT", 1, ACPI_LOGICAL_ADDRESSING, + (struct acpi_table_header **) + &ecdt_ptr); + if (ACPI_FAILURE(status)) + return -ENODEV; + + printk(KERN_INFO PREFIX "Found ECDT\n"); + + /* + * Generate a temporary ec context to use until the namespace is scanned + */ + ec_ecdt = kmalloc(sizeof(union acpi_ec), GFP_KERNEL); + if (!ec_ecdt) + return -ENOMEM; + memset(ec_ecdt, 0, sizeof(union acpi_ec)); + + init_MUTEX(&ec_ecdt->intr.sem); + init_waitqueue_head(&ec_ecdt->intr.wait); + ec_ecdt->common.command_addr = ecdt_ptr->ec_control; + ec_ecdt->common.status_addr = ecdt_ptr->ec_control; + ec_ecdt->common.data_addr = ecdt_ptr->ec_data; + ec_ecdt->common.gpe_bit = ecdt_ptr->gpe_bit; /* use the GL just to be safe */ - ec_ecdt->global_lock = TRUE; - ec_ecdt->uid = ecdt_ptr->uid; + ec_ecdt->common.global_lock = TRUE; + ec_ecdt->common.uid = ecdt_ptr->uid; status = - acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->handle); + acpi_get_handle(NULL, ecdt_ptr->ec_id, &ec_ecdt->common.handle); if (ACPI_FAILURE(status)) { goto error; } return 0; - error: - ACPI_EXCEPTION((AE_INFO, status, "Could not use ECDT")); + error: + printk(KERN_ERR PREFIX "Could not use ECDT\n"); kfree(ec_ecdt); ec_ecdt = NULL; @@ -970,14 +1480,14 @@ int __init acpi_ec_ecdt_probe(void) /* * Install GPE handler */ - status = acpi_install_gpe_handler(NULL, ec_ecdt->gpe_bit, + status = acpi_install_gpe_handler(NULL, ec_ecdt->common.gpe_bit, ACPI_GPE_EDGE_TRIGGERED, &acpi_ec_gpe_handler, ec_ecdt); if (ACPI_FAILURE(status)) { goto error; } - acpi_set_gpe_type(NULL, ec_ecdt->gpe_bit, ACPI_GPE_TYPE_RUNTIME); - acpi_enable_gpe(NULL, ec_ecdt->gpe_bit, ACPI_NOT_ISR); + acpi_set_gpe_type(NULL, ec_ecdt->common.gpe_bit, ACPI_GPE_TYPE_RUNTIME); + acpi_enable_gpe(NULL, ec_ecdt->common.gpe_bit, ACPI_NOT_ISR); status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT, ACPI_ADR_SPACE_EC, @@ -985,7 +1495,7 @@ int __init acpi_ec_ecdt_probe(void) &acpi_ec_space_setup, ec_ecdt); if (ACPI_FAILURE(status)) { - acpi_remove_gpe_handler(NULL, ec_ecdt->gpe_bit, + acpi_remove_gpe_handler(NULL, ec_ecdt->common.gpe_bit, &acpi_ec_gpe_handler); goto error; } @@ -993,7 +1503,7 @@ int __init acpi_ec_ecdt_probe(void) return 0; error: - ACPI_EXCEPTION((AE_INFO, status, "Could not use ECDT")); + printk(KERN_ERR PREFIX "Could not use ECDT\n"); kfree(ec_ecdt); ec_ecdt = NULL; @@ -1052,13 +1562,13 @@ static int __init acpi_ec_set_intr_mode(char *str) return 0; if (intr) { - acpi_ec_mode = EC_INTR; + acpi_ec_poll_mode = EC_INTR; + acpi_ec_driver.ops.add = acpi_ec_intr_add; } else { - acpi_ec_mode = EC_POLL; + acpi_ec_poll_mode = EC_POLL; + acpi_ec_driver.ops.add = acpi_ec_poll_add; } - acpi_ec_driver.ops.add = acpi_ec_add; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "EC %s mode.\n", intr ? "interrupt" : "polling")); - + printk(KERN_INFO PREFIX "EC %s mode.\n", intr ? "interrupt" : "polling"); return 1; } diff --git a/trunk/drivers/acpi/events/evmisc.c b/trunk/drivers/acpi/events/evmisc.c index ee2a10bf9077..6eef4efddcf6 100644 --- a/trunk/drivers/acpi/events/evmisc.c +++ b/trunk/drivers/acpi/events/evmisc.c @@ -342,8 +342,20 @@ static u32 acpi_ev_global_lock_handler(void *context) if (acquired) { /* Got the lock, now wake all threads waiting for it */ + acpi_gbl_global_lock_acquired = TRUE; - acpi_ev_global_lock_thread(context); + + /* Run the Global Lock thread which will signal all waiting threads */ + + status = + acpi_os_execute(OSL_GLOBAL_LOCK_HANDLER, + acpi_ev_global_lock_thread, context); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, + "Could not queue Global Lock thread")); + + return (ACPI_INTERRUPT_NOT_HANDLED); + } } return (ACPI_INTERRUPT_HANDLED); diff --git a/trunk/drivers/acpi/events/evrgnini.c b/trunk/drivers/acpi/events/evrgnini.c index 203d1359190a..5b3c7a85eb9a 100644 --- a/trunk/drivers/acpi/events/evrgnini.c +++ b/trunk/drivers/acpi/events/evrgnini.c @@ -225,12 +225,13 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, if (! (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 */ diff --git a/trunk/drivers/acpi/ibm_acpi.c b/trunk/drivers/acpi/ibm_acpi.c index 003a9876c968..15fc12482ba0 100644 --- a/trunk/drivers/acpi/ibm_acpi.c +++ b/trunk/drivers/acpi/ibm_acpi.c @@ -1702,11 +1702,13 @@ static struct ibm_struct ibms[] = { .name = "brightness", .read = brightness_read, .write = brightness_write, + .experimental = 1, }, { .name = "volume", .read = volume_read, .write = volume_write, + .experimental = 1, }, { .name = "fan", diff --git a/trunk/drivers/acpi/osl.c b/trunk/drivers/acpi/osl.c index c84286cbbe25..068fe4f100b0 100644 --- a/trunk/drivers/acpi/osl.c +++ b/trunk/drivers/acpi/osl.c @@ -73,7 +73,6 @@ static unsigned int acpi_irq_irq; static acpi_osd_handler acpi_irq_handler; static void *acpi_irq_context; static struct workqueue_struct *kacpid_wq; -static struct workqueue_struct *kacpi_notify_wq; acpi_status acpi_os_initialize(void) { @@ -92,9 +91,8 @@ acpi_status acpi_os_initialize1(void) return AE_NULL_ENTRY; } kacpid_wq = create_singlethread_workqueue("kacpid"); - kacpi_notify_wq = create_singlethread_workqueue("kacpi_notify"); BUG_ON(!kacpid_wq); - BUG_ON(!kacpi_notify_wq); + return AE_OK; } @@ -106,7 +104,6 @@ acpi_status acpi_os_terminate(void) } destroy_workqueue(kacpid_wq); - destroy_workqueue(kacpi_notify_wq); return AE_OK; } @@ -569,7 +566,10 @@ void acpi_os_derive_pci_id(acpi_handle rhandle, /* upper bound */ static void acpi_os_execute_deferred(void *context) { - struct acpi_os_dpc *dpc = (struct acpi_os_dpc *)context; + struct acpi_os_dpc *dpc = NULL; + + + dpc = (struct acpi_os_dpc *)context; if (!dpc) { printk(KERN_ERR PREFIX "Invalid (NULL) context\n"); return; @@ -604,12 +604,14 @@ acpi_status acpi_os_execute(acpi_execute_type type, struct acpi_os_dpc *dpc; struct work_struct *task; + ACPI_FUNCTION_TRACE("os_queue_for_execution"); + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Scheduling function [%p(%p)] for deferred execution.\n", function, context)); if (!function) - return AE_BAD_PARAMETER; + return_ACPI_STATUS(AE_BAD_PARAMETER); /* * Allocate/initialize DPC structure. Note that this memory will be @@ -622,20 +624,26 @@ acpi_status acpi_os_execute(acpi_execute_type type, * from the same memory. */ - dpc = kmalloc(sizeof(struct acpi_os_dpc) + - sizeof(struct work_struct), GFP_ATOMIC); + dpc = + kmalloc(sizeof(struct acpi_os_dpc) + sizeof(struct work_struct), + GFP_ATOMIC); if (!dpc) - return AE_NO_MEMORY; + return_ACPI_STATUS(AE_NO_MEMORY); + dpc->function = function; dpc->context = context; + task = (void *)(dpc + 1); INIT_WORK(task, acpi_os_execute_deferred, (void *)dpc); - if (!queue_work((type == OSL_NOTIFY_HANDLER)? - kacpi_notify_wq : kacpid_wq, task)) { - status = AE_ERROR; + + if (!queue_work(kacpid_wq, task)) { + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, + "Call to queue_work() failed.\n")); kfree(dpc); + status = AE_ERROR; } - return status; + + return_ACPI_STATUS(status); } EXPORT_SYMBOL(acpi_os_execute); diff --git a/trunk/drivers/acpi/processor_idle.c b/trunk/drivers/acpi/processor_idle.c index 429a39dbd75d..0a395fca843b 100644 --- a/trunk/drivers/acpi/processor_idle.c +++ b/trunk/drivers/acpi/processor_idle.c @@ -219,23 +219,6 @@ static void acpi_safe_halt(void) static atomic_t c3_cpu_count; -/* Common C-state entry for C2, C3, .. */ -static void acpi_cstate_enter(struct acpi_processor_cx *cstate) -{ - if (cstate->space_id == ACPI_CSTATE_FFH) { - /* Call into architectural FFH based C-state */ - acpi_processor_ffh_cstate_enter(cstate); - } else { - int unused; - /* IO port based C-state */ - inb(cstate->address); - /* Dummy wait op - must do something useless after P_LVL2 read - because chipsets cannot guarantee that STPCLK# signal - gets asserted in time to freeze execution properly. */ - unused = inl(acpi_fadt.xpm_tmr_blk.address); - } -} - static void acpi_processor_idle(void) { struct acpi_processor *pr = NULL; @@ -378,7 +361,11 @@ static void acpi_processor_idle(void) /* Get start time (ticks) */ t1 = inl(acpi_fadt.xpm_tmr_blk.address); /* Invoke C2 */ - acpi_cstate_enter(cx); + inb(cx->address); + /* Dummy wait op - must do something useless after P_LVL2 read + because chipsets cannot guarantee that STPCLK# signal + gets asserted in time to freeze execution properly. */ + t2 = inl(acpi_fadt.xpm_tmr_blk.address); /* Get end time (ticks) */ t2 = inl(acpi_fadt.xpm_tmr_blk.address); @@ -414,7 +401,9 @@ static void acpi_processor_idle(void) /* Get start time (ticks) */ t1 = inl(acpi_fadt.xpm_tmr_blk.address); /* Invoke C3 */ - acpi_cstate_enter(cx); + inb(cx->address); + /* Dummy wait op (see above) */ + t2 = inl(acpi_fadt.xpm_tmr_blk.address); /* Get end time (ticks) */ t2 = inl(acpi_fadt.xpm_tmr_blk.address); if (pr->flags.bm_check) { @@ -639,16 +628,20 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) return 0; } -static int acpi_processor_get_power_info_default(struct acpi_processor *pr) +static int acpi_processor_get_power_info_default_c1(struct acpi_processor *pr) { - if (!pr->power.states[ACPI_STATE_C1].valid) { - /* set the first C-State to C1 */ - /* all processors need to support C1 */ - pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; - pr->power.states[ACPI_STATE_C1].valid = 1; - } - /* the C0 state only exists as a filler in our array */ + + /* Zero initialize all the C-states info. */ + memset(pr->power.states, 0, sizeof(pr->power.states)); + + /* set the first C-State to C1 */ + pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; + + /* the C0 state only exists as a filler in our array, + * and all processors need to support C1 */ pr->power.states[ACPI_STATE_C0].valid = 1; + pr->power.states[ACPI_STATE_C1].valid = 1; + return 0; } @@ -665,7 +658,12 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) if (nocst) return -ENODEV; - current_count = 0; + current_count = 1; + + /* Zero initialize C2 onwards and prepare for fresh CST lookup */ + for (i = 2; i < ACPI_PROCESSOR_MAX_POWER; i++) + memset(&(pr->power.states[i]), 0, + sizeof(struct acpi_processor_cx)); status = acpi_evaluate_object(pr->handle, "_CST", NULL, &buffer); if (ACPI_FAILURE(status)) { @@ -720,39 +718,22 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) (reg->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE)) continue; + cx.address = (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) ? + 0 : reg->address; + /* There should be an easy way to extract an integer... */ obj = (union acpi_object *)&(element->package.elements[1]); if (obj->type != ACPI_TYPE_INTEGER) continue; cx.type = obj->integer.value; - /* - * Some buggy BIOSes won't list C1 in _CST - - * Let acpi_processor_get_power_info_default() handle them later - */ - if (i == 1 && cx.type != ACPI_STATE_C1) - current_count++; - - cx.address = reg->address; - cx.index = current_count + 1; - - cx.space_id = ACPI_CSTATE_SYSTEMIO; - if (reg->space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) { - if (acpi_processor_ffh_cstate_probe - (pr->id, &cx, reg) == 0) { - cx.space_id = ACPI_CSTATE_FFH; - } else if (cx.type != ACPI_STATE_C1) { - /* - * C1 is a special case where FIXED_HARDWARE - * can be handled in non-MWAIT way as well. - * In that case, save this _CST entry info. - * That is, we retain space_id of SYSTEM_IO for - * halt based C1. - * Otherwise, ignore this info and continue. - */ - continue; - } - } + + if ((cx.type != ACPI_STATE_C1) && + (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO)) + continue; + + if ((cx.type < ACPI_STATE_C2) || (cx.type > ACPI_STATE_C3)) + continue; obj = (union acpi_object *)&(element->package.elements[2]); if (obj->type != ACPI_TYPE_INTEGER) @@ -957,18 +938,12 @@ static int acpi_processor_get_power_info(struct acpi_processor *pr) /* NOTE: the idle thread may not be running while calling * this function */ - /* Zero initialize all the C-states info. */ - memset(pr->power.states, 0, sizeof(pr->power.states)); - + /* Adding C1 state */ + acpi_processor_get_power_info_default_c1(pr); result = acpi_processor_get_power_info_cst(pr); if (result == -ENODEV) acpi_processor_get_power_info_fadt(pr); - if (result) - return result; - - acpi_processor_get_power_info_default(pr); - pr->power.count = acpi_processor_power_verify(pr); /* diff --git a/trunk/drivers/acpi/sbs.c b/trunk/drivers/acpi/sbs.c index 8908a975e575..62bef0b3b614 100644 --- a/trunk/drivers/acpi/sbs.c +++ b/trunk/drivers/acpi/sbs.c @@ -98,11 +98,11 @@ static int update_info_mode = UPDATE_INFO_MODE; static int update_time = UPDATE_TIME; static int update_time2 = 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); +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); static int acpi_sbs_add(struct acpi_device *device); static int acpi_sbs_remove(struct acpi_device *device, int type); @@ -1685,16 +1685,10 @@ static int acpi_sbs_add(struct acpi_device *device) int acpi_sbs_remove(struct acpi_device *device, int type) { - struct acpi_sbs *sbs = NULL; + struct acpi_sbs *sbs = (struct acpi_sbs *)acpi_driver_data(device); int id; - if (!device) { - return -EINVAL; - } - - sbs = (struct acpi_sbs *)acpi_driver_data(device); - - if (!sbs) { + if (!device || !sbs) { return -EINVAL; } diff --git a/trunk/drivers/misc/Kconfig b/trunk/drivers/misc/Kconfig index fa7acc2c5c6d..3df0e7a07c46 100644 --- a/trunk/drivers/misc/Kconfig +++ b/trunk/drivers/misc/Kconfig @@ -57,23 +57,4 @@ 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 - . - - If you have an MSI S270 laptop, say Y or M here. - endmenu diff --git a/trunk/drivers/misc/Makefile b/trunk/drivers/misc/Makefile index 9a91c1ee8497..d65ece76095a 100644 --- a/trunk/drivers/misc/Makefile +++ b/trunk/drivers/misc/Makefile @@ -5,7 +5,6 @@ obj- := misc.o # Dummy rule to force built-in.o to be made obj-$(CONFIG_IBM_ASM) += ibmasm/ obj-$(CONFIG_HDPU_FEATURES) += hdpuftrs/ -obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o obj-$(CONFIG_LKDTM) += lkdtm.o obj-$(CONFIG_TIFM_CORE) += tifm_core.o obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o diff --git a/trunk/drivers/misc/msi-laptop.c b/trunk/drivers/misc/msi-laptop.c deleted file mode 100644 index fdb7153f4426..000000000000 --- a/trunk/drivers/misc/msi-laptop.c +++ /dev/null @@ -1,395 +0,0 @@ -/*-*-linux-c-*-*/ - -/* - Copyright (C) 2006 Lennart Poettering - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. - */ - -/* - * msi-laptop.c - MSI S270 laptop support. This laptop is sold under - * various brands, including "Cytron/TCM/Medion/Tchibo MD96100". - * - * This driver exports a few files in /sys/devices/platform/msi-laptop-pf/: - * - * lcd_level - Screen brightness: contains a single integer in the - * range 0..8. (rw) - * - * auto_brightness - Enable automatic brightness control: contains - * either 0 or 1. If set to 1 the hardware adjusts the screen - * brightness automatically when the power cord is - * plugged/unplugged. (rw) - * - * wlan - WLAN subsystem enabled: contains either 0 or 1. (ro) - * - * bluetooth - Bluetooth subsystem enabled: contains either 0 or 1 - * Please note that this file is constantly 0 if no Bluetooth - * hardware is available. (ro) - * - * In addition to these platform device attributes the driver - * registers itself in the Linux backlight control subsystem and is - * available to userspace under /sys/class/backlight/msi-laptop-bl/. - * - * This driver might work on other laptops produced by MSI. If you - * want to try it you can pass force=1 as argument to the module which - * will force it to load even when the DMI data doesn't identify the - * laptop as MSI S270. YMMV. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define MSI_DRIVER_VERSION "0.5" - -#define MSI_LCD_LEVEL_MAX 9 - -#define MSI_EC_COMMAND_WIRELESS 0x10 -#define MSI_EC_COMMAND_LCD_LEVEL 0x11 - -static int force; -module_param(force, bool, 0); -MODULE_PARM_DESC(force, "Force driver load, ignore DMI data"); - -static int auto_brightness; -module_param(auto_brightness, int, 0); -MODULE_PARM_DESC(auto_brightness, "Enable automatic brightness control (0: disabled; 1: enabled; 2: don't touch)"); - -/* Hardware access */ - -static int set_lcd_level(int level) -{ - u8 buf[2]; - - if (level < 0 || level >= MSI_LCD_LEVEL_MAX) - return -EINVAL; - - buf[0] = 0x80; - buf[1] = (u8) (level*31); - - return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, buf, sizeof(buf), NULL, 0); -} - -static int get_lcd_level(void) -{ - u8 wdata = 0, rdata; - int result; - - result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, &wdata, 1, &rdata, 1); - if (result < 0) - return result; - - return (int) rdata / 31; -} - -static int get_auto_brightness(void) -{ - u8 wdata = 4, rdata; - int result; - - result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, &wdata, 1, &rdata, 1); - if (result < 0) - return result; - - return !!(rdata & 8); -} - -static int set_auto_brightness(int enable) -{ - u8 wdata[2], rdata; - int result; - - wdata[0] = 4; - - result = ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 1, &rdata, 1); - if (result < 0) - return result; - - wdata[0] = 0x84; - wdata[1] = (rdata & 0xF7) | (enable ? 8 : 0); - - return ec_transaction(MSI_EC_COMMAND_LCD_LEVEL, wdata, 2, NULL, 0); -} - -static int get_wireless_state(int *wlan, int *bluetooth) -{ - u8 wdata = 0, rdata; - int result; - - result = ec_transaction(MSI_EC_COMMAND_WIRELESS, &wdata, 1, &rdata, 1); - if (result < 0) - return -1; - - if (wlan) - *wlan = !!(rdata & 8); - - if (bluetooth) - *bluetooth = !!(rdata & 128); - - return 0; -} - -/* Backlight device stuff */ - -static int bl_get_brightness(struct backlight_device *b) -{ - return get_lcd_level(); -} - - -static int bl_update_status(struct backlight_device *b) -{ - return set_lcd_level(b->props->brightness); -} - -static struct backlight_properties msibl_props = { - .owner = THIS_MODULE, - .get_brightness = bl_get_brightness, - .update_status = bl_update_status, - .max_brightness = MSI_LCD_LEVEL_MAX-1, -}; - -static struct backlight_device *msibl_device; - -/* Platform device */ - -static ssize_t show_wlan(struct device *dev, - struct device_attribute *attr, char *buf) -{ - - int ret, enabled; - - ret = get_wireless_state(&enabled, NULL); - if (ret < 0) - return ret; - - return sprintf(buf, "%i\n", enabled); -} - -static ssize_t show_bluetooth(struct device *dev, - struct device_attribute *attr, char *buf) -{ - - int ret, enabled; - - ret = get_wireless_state(NULL, &enabled); - if (ret < 0) - return ret; - - return sprintf(buf, "%i\n", enabled); -} - -static ssize_t show_lcd_level(struct device *dev, - struct device_attribute *attr, char *buf) -{ - - int ret; - - ret = get_lcd_level(); - if (ret < 0) - return ret; - - return sprintf(buf, "%i\n", ret); -} - -static ssize_t store_lcd_level(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - - int level, ret; - - if (sscanf(buf, "%i", &level) != 1 || (level < 0 || level >= MSI_LCD_LEVEL_MAX)) - return -EINVAL; - - ret = set_lcd_level(level); - if (ret < 0) - return ret; - - return count; -} - -static ssize_t show_auto_brightness(struct device *dev, - struct device_attribute *attr, char *buf) -{ - - int ret; - - ret = get_auto_brightness(); - if (ret < 0) - return ret; - - return sprintf(buf, "%i\n", ret); -} - -static ssize_t store_auto_brightness(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - - int enable, ret; - - if (sscanf(buf, "%i", &enable) != 1 || (enable != (enable & 1))) - return -EINVAL; - - ret = set_auto_brightness(enable); - if (ret < 0) - return ret; - - return count; -} - -static DEVICE_ATTR(lcd_level, 0644, show_lcd_level, store_lcd_level); -static DEVICE_ATTR(auto_brightness, 0644, show_auto_brightness, store_auto_brightness); -static DEVICE_ATTR(bluetooth, 0444, show_bluetooth, NULL); -static DEVICE_ATTR(wlan, 0444, show_wlan, NULL); - -static struct attribute *msipf_attributes[] = { - &dev_attr_lcd_level.attr, - &dev_attr_auto_brightness.attr, - &dev_attr_bluetooth.attr, - &dev_attr_wlan.attr, - NULL -}; - -static struct attribute_group msipf_attribute_group = { - .attrs = msipf_attributes -}; - -static struct platform_driver msipf_driver = { - .driver = { - .name = "msi-laptop-pf", - .owner = THIS_MODULE, - } -}; - -static struct platform_device *msipf_device; - -/* Initialization */ - -static struct dmi_system_id __initdata msi_dmi_table[] = { - { - .ident = "MSI S270", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "MICRO-STAR INT'L CO.,LTD"), - DMI_MATCH(DMI_PRODUCT_NAME, "MS-1013"), - } - }, - { - .ident = "Medion MD96100", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "NOTEBOOK"), - DMI_MATCH(DMI_PRODUCT_NAME, "SAM2000"), - } - }, - { } -}; - - -static int __init msi_init(void) -{ - int ret; - - if (acpi_disabled) - return -ENODEV; - - if (!force && !dmi_check_system(msi_dmi_table)) - return -ENODEV; - - if (auto_brightness < 0 || auto_brightness > 2) - return -EINVAL; - - /* Register backlight stuff */ - - msibl_device = backlight_device_register("msi-laptop-bl", NULL, &msibl_props); - if (IS_ERR(msibl_device)) - return PTR_ERR(msibl_device); - - ret = platform_driver_register(&msipf_driver); - if (ret) - goto fail_backlight; - - /* Register platform stuff */ - - msipf_device = platform_device_alloc("msi-laptop-pf", -1); - if (!msipf_device) { - ret = -ENOMEM; - goto fail_platform_driver; - } - - ret = platform_device_add(msipf_device); - if (ret) - goto fail_platform_device1; - - ret = sysfs_create_group(&msipf_device->dev.kobj, &msipf_attribute_group); - if (ret) - goto fail_platform_device2; - - /* Disable automatic brightness control by default because - * this module was probably loaded to do brightness control in - * software. */ - - if (auto_brightness != 2) - set_auto_brightness(auto_brightness); - - printk(KERN_INFO "msi-laptop: driver "MSI_DRIVER_VERSION" successfully loaded.\n"); - - return 0; - -fail_platform_device2: - - platform_device_del(msipf_device); - -fail_platform_device1: - - platform_device_put(msipf_device); - -fail_platform_driver: - - platform_driver_unregister(&msipf_driver); - -fail_backlight: - - backlight_device_unregister(msibl_device); - - return ret; -} - -static void __exit msi_cleanup(void) -{ - - sysfs_remove_group(&msipf_device->dev.kobj, &msipf_attribute_group); - platform_device_unregister(msipf_device); - platform_driver_unregister(&msipf_driver); - backlight_device_unregister(msibl_device); - - /* Enable automatic brightness control again */ - if (auto_brightness != 2) - set_auto_brightness(1); - - printk(KERN_INFO "msi-laptop: driver unloaded.\n"); -} - -module_init(msi_init); -module_exit(msi_cleanup); - -MODULE_AUTHOR("Lennart Poettering"); -MODULE_DESCRIPTION("MSI Laptop Support"); -MODULE_VERSION(MSI_DRIVER_VERSION); -MODULE_LICENSE("GPL"); diff --git a/trunk/include/acpi/pdc_intel.h b/trunk/include/acpi/pdc_intel.h index e72bfdd887f9..c5472be6f3a2 100644 --- a/trunk/include/acpi/pdc_intel.h +++ b/trunk/include/acpi/pdc_intel.h @@ -13,7 +13,6 @@ #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 | \ @@ -24,10 +23,8 @@ 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 | \ - ACPI_PDC_C_C1_FFH | \ - ACPI_PDC_C_C2C3_FFH) +#define ACPI_PDC_C_CAPABILITY_SMP (ACPI_PDC_SMP_C2C3 | \ + ACPI_PDC_SMP_C1PT | \ + ACPI_PDC_C_C1_HALT) #endif /* __PDC_INTEL_H__ */ diff --git a/trunk/include/acpi/processor.h b/trunk/include/acpi/processor.h index 7798d2a9f793..9dd5b75961f8 100644 --- a/trunk/include/acpi/processor.h +++ b/trunk/include/acpi/processor.h @@ -29,9 +29,6 @@ #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; @@ -61,8 +58,6 @@ struct acpi_processor_cx { u8 valid; u8 type; u32 address; - u8 space_id; - u8 index; u32 latency; u32 latency_ticks; u32 power; @@ -211,9 +206,6 @@ void arch_acpi_processor_init_pdc(struct acpi_processor *pr); #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 @@ -222,16 +214,6 @@ static inline void acpi_processor_power_init_bm_check(struct 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 */ diff --git a/trunk/include/asm-i386/processor.h b/trunk/include/asm-i386/processor.h index e0ddca94d50c..2277127696d2 100644 --- a/trunk/include/asm-i386/processor.h +++ b/trunk/include/asm-i386/processor.h @@ -306,8 +306,6 @@ static inline void __mwait(unsigned long eax, unsigned long ecx) : :"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; diff --git a/trunk/include/asm-x86_64/processor.h b/trunk/include/asm-x86_64/processor.h index cef17e0f828c..de9c3147ee4c 100644 --- a/trunk/include/asm-x86_64/processor.h +++ b/trunk/include/asm-x86_64/processor.h @@ -475,8 +475,6 @@ static inline void __mwait(unsigned long eax, unsigned long ecx) : :"a" (eax), "c" (ecx)); } -extern void mwait_idle_with_hints(unsigned long eax, unsigned long ecx); - #define stack_current() \ ({ \ struct thread_info *ti; \ diff --git a/trunk/include/linux/acpi.h b/trunk/include/linux/acpi.h index 2b0c955590fe..88b5dfd8ee12 100644 --- a/trunk/include/linux/acpi.h +++ b/trunk/include/linux/acpi.h @@ -494,9 +494,6 @@ void acpi_pci_unregister_driver(struct acpi_pci_driver *driver); extern 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*/