From 08fc62b477b49e544d756edd8dd3e6836c085aa6 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Tue, 19 Jan 2010 16:55:41 -0700 Subject: [PATCH] --- yaml --- r: 179671 b: refs/heads/master c: 2205cbe8ecaf5f3ab911cef839c94d05ea5b0c76 h: refs/heads/master i: 179669: 5a67a81c595e0e596c09c9a0e61d69e64dc14f07 179667: c142984e4da7644d37981e26cdd196aafa6f8bd9 179663: bb700814380e6868fd174a0b615d7983961a35e6 v: v3 --- [refs] | 2 +- trunk/arch/x86/kernel/acpi/boot.c | 22 +- trunk/drivers/acpi/acpi_pad.c | 37 ++- trunk/drivers/acpi/bus.c | 7 +- trunk/drivers/acpi/ec.c | 126 ++++----- trunk/drivers/acpi/pci_link.c | 2 +- trunk/drivers/acpi/pci_root.c | 2 +- trunk/drivers/acpi/power.c | 2 +- trunk/drivers/acpi/power_meter.c | 4 +- trunk/drivers/acpi/processor_idle.c | 64 +++-- trunk/drivers/acpi/processor_pdc.c | 32 ++- trunk/drivers/acpi/processor_thermal.c | 3 +- trunk/drivers/acpi/sbs.c | 3 - trunk/drivers/acpi/sbshc.c | 2 +- trunk/drivers/acpi/video.c | 43 ---- trunk/drivers/platform/x86/Kconfig | 1 - trunk/drivers/platform/x86/eeepc-laptop.c | 298 ++++++++++------------ trunk/drivers/platform/x86/sony-laptop.c | 9 +- trunk/include/acpi/platform/aclinux.h | 2 +- trunk/include/linux/acpi.h | 6 +- 20 files changed, 300 insertions(+), 367 deletions(-) diff --git a/[refs] b/[refs] index ef30ada41583..4d77e94db2f7 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: be6066f34c948ccf4adcc90bbeb1fd335d663303 +refs/heads/master: 2205cbe8ecaf5f3ab911cef839c94d05ea5b0c76 diff --git a/trunk/arch/x86/kernel/acpi/boot.c b/trunk/arch/x86/kernel/acpi/boot.c index 036d28adf59d..fb1035cd9a6a 100644 --- a/trunk/arch/x86/kernel/acpi/boot.c +++ b/trunk/arch/x86/kernel/acpi/boot.c @@ -1529,10 +1529,16 @@ static struct dmi_system_id __initdata acpi_dmi_table_late[] = { * if acpi_blacklisted() acpi_disabled = 1; * acpi_irq_model=... * ... + * + * return value: (currently ignored) + * 0: success + * !0: failure */ -void __init acpi_boot_table_init(void) +int __init acpi_boot_table_init(void) { + int error; + dmi_check_system(acpi_dmi_table); /* @@ -1540,14 +1546,15 @@ void __init acpi_boot_table_init(void) * One exception: acpi=ht continues far enough to enumerate LAPICs */ if (acpi_disabled && !acpi_ht) - return; + return 1; /* * Initialize the ACPI boot-time table parser. */ - if (acpi_table_init()) { + error = acpi_table_init(); + if (error) { disable_acpi(); - return; + return error; } acpi_table_parse(ACPI_SIG_BOOT, acpi_parse_sbf); @@ -1555,15 +1562,18 @@ void __init acpi_boot_table_init(void) /* * blacklist may disable ACPI entirely */ - if (acpi_blacklisted()) { + error = acpi_blacklisted(); + if (error) { if (acpi_force) { printk(KERN_WARNING PREFIX "acpi=force override\n"); } else { printk(KERN_WARNING PREFIX "Disabling ACPI support\n"); disable_acpi(); - return; + return error; } } + + return 0; } int __init early_acpi_boot_init(void) diff --git a/trunk/drivers/acpi/acpi_pad.c b/trunk/drivers/acpi/acpi_pad.c index 7e52295f1ecc..97991ac6f5fc 100644 --- a/trunk/drivers/acpi/acpi_pad.c +++ b/trunk/drivers/acpi/acpi_pad.c @@ -208,7 +208,7 @@ static int power_saving_thread(void *data) * the mechanism only works when all CPUs have RT task running, * as if one CPU hasn't RT task, RT task from other CPUs will * borrow CPU time from this CPU and cause RT task use > 95% - * CPU time. To make 'avoid starvation' work, takes a nap here. + * CPU time. To make 'avoid staration' work, takes a nap here. */ if (do_sleep) schedule_timeout_killable(HZ * idle_pct / 100); @@ -222,18 +222,14 @@ static struct task_struct *ps_tsks[NR_CPUS]; static unsigned int ps_tsk_num; static int create_power_saving_task(void) { - int rc = -ENOMEM; - ps_tsks[ps_tsk_num] = kthread_run(power_saving_thread, (void *)(unsigned long)ps_tsk_num, "power_saving/%d", ps_tsk_num); - rc = IS_ERR(ps_tsks[ps_tsk_num]) ? PTR_ERR(ps_tsks[ps_tsk_num]) : 0; - if (!rc) + if (ps_tsks[ps_tsk_num]) { ps_tsk_num++; - else - ps_tsks[ps_tsk_num] = NULL; - - return rc; + return 0; + } + return -EINVAL; } static void destroy_power_saving_task(void) @@ -241,7 +237,6 @@ static void destroy_power_saving_task(void) if (ps_tsk_num > 0) { ps_tsk_num--; kthread_stop(ps_tsks[ps_tsk_num]); - ps_tsks[ps_tsk_num] = NULL; } } @@ -258,7 +253,7 @@ static void set_power_saving_task_num(unsigned int num) } } -static void acpi_pad_idle_cpus(unsigned int num_cpus) +static int acpi_pad_idle_cpus(unsigned int num_cpus) { get_online_cpus(); @@ -266,6 +261,7 @@ static void acpi_pad_idle_cpus(unsigned int num_cpus) set_power_saving_task_num(num_cpus); put_online_cpus(); + return 0; } static uint32_t acpi_pad_idle_cpus_num(void) @@ -373,21 +369,19 @@ static void acpi_pad_remove_sysfs(struct acpi_device *device) static int acpi_pad_pur(acpi_handle handle, int *num_cpus) { struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + acpi_status status; union acpi_object *package; int rev, num, ret = -EINVAL; - if (ACPI_FAILURE(acpi_evaluate_object(handle, "_PUR", NULL, &buffer))) - return -EINVAL; - - if (!buffer.length || !buffer.pointer) + status = acpi_evaluate_object(handle, "_PUR", NULL, &buffer); + if (ACPI_FAILURE(status)) return -EINVAL; - package = buffer.pointer; if (package->type != ACPI_TYPE_PACKAGE || package->package.count != 2) goto out; rev = package->package.elements[0].integer.value; num = package->package.elements[1].integer.value; - if (rev != 1 || num < 0) + if (rev != 1) goto out; *num_cpus = num; ret = 0; @@ -416,7 +410,7 @@ static void acpi_pad_ost(acpi_handle handle, int stat, static void acpi_pad_handle_notify(acpi_handle handle) { - int num_cpus; + int num_cpus, ret; uint32_t idle_cpus; mutex_lock(&isolated_cpus_lock); @@ -424,9 +418,12 @@ static void acpi_pad_handle_notify(acpi_handle handle) mutex_unlock(&isolated_cpus_lock); return; } - acpi_pad_idle_cpus(num_cpus); + ret = acpi_pad_idle_cpus(num_cpus); idle_cpus = acpi_pad_idle_cpus_num(); - acpi_pad_ost(handle, 0, idle_cpus); + if (!ret) + acpi_pad_ost(handle, 0, idle_cpus); + else + acpi_pad_ost(handle, 1, 0); mutex_unlock(&isolated_cpus_lock); } diff --git a/trunk/drivers/acpi/bus.c b/trunk/drivers/acpi/bus.c index a52126e46307..cf761b904e4a 100644 --- a/trunk/drivers/acpi/bus.c +++ b/trunk/drivers/acpi/bus.c @@ -490,14 +490,9 @@ static void acpi_bus_osc_support(void) capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; capbuf[OSC_SUPPORT_TYPE] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */ -#if defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) ||\ - defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE) +#ifdef CONFIG_ACPI_PROCESSOR_AGGREGATOR capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PAD_SUPPORT; #endif - -#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE) - capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PPC_OST_SUPPORT; -#endif if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle))) return; if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) diff --git a/trunk/drivers/acpi/ec.c b/trunk/drivers/acpi/ec.c index d6471bb6852f..fd1801bdee66 100644 --- a/trunk/drivers/acpi/ec.c +++ b/trunk/drivers/acpi/ec.c @@ -201,13 +201,14 @@ static void advance_transaction(struct acpi_ec *ec, u8 status) spin_unlock_irqrestore(&ec->curr_lock, flags); } -static int acpi_ec_sync_query(struct acpi_ec *ec); +static void acpi_ec_gpe_query(void *ec_cxt); -static int ec_check_sci_sync(struct acpi_ec *ec, u8 state) +static int ec_check_sci(struct acpi_ec *ec, u8 state) { if (state & ACPI_EC_FLAG_SCI) { if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) - return acpi_ec_sync_query(ec); + return acpi_os_execute(OSL_EC_BURST_HANDLER, + acpi_ec_gpe_query, ec); } return 0; } @@ -248,6 +249,11 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, { unsigned long tmp; int ret = 0; + pr_debug(PREFIX "transaction start\n"); + /* disable GPE during transaction if storm is detected */ + if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { + acpi_disable_gpe(NULL, ec->gpe); + } if (EC_FLAGS_MSI) udelay(ACPI_EC_MSI_UDELAY); /* start transaction */ @@ -259,9 +265,20 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); spin_unlock_irqrestore(&ec->curr_lock, tmp); ret = ec_poll(ec); + pr_debug(PREFIX "transaction end\n"); spin_lock_irqsave(&ec->curr_lock, tmp); ec->curr = NULL; spin_unlock_irqrestore(&ec->curr_lock, tmp); + if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { + /* check if we received SCI during transaction */ + ec_check_sci(ec, acpi_ec_read_status(ec)); + /* it is safe to enable GPE outside of transaction */ + acpi_enable_gpe(NULL, ec->gpe); + } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { + pr_info(PREFIX "GPE storm detected, " + "transactions will use polling mode\n"); + set_bit(EC_FLAGS_GPE_STORM, &ec->flags); + } return ret; } @@ -304,26 +321,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) status = -ETIME; goto end; } - pr_debug(PREFIX "transaction start\n"); - /* disable GPE during transaction if storm is detected */ - if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { - acpi_disable_gpe(NULL, ec->gpe); - } - status = acpi_ec_transaction_unlocked(ec, t); - - /* check if we received SCI during transaction */ - ec_check_sci_sync(ec, acpi_ec_read_status(ec)); - if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { - msleep(1); - /* it is safe to enable GPE outside of transaction */ - acpi_enable_gpe(NULL, ec->gpe); - } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { - pr_info(PREFIX "GPE storm detected, " - "transactions will use polling mode\n"); - set_bit(EC_FLAGS_GPE_STORM, &ec->flags); - } - pr_debug(PREFIX "transaction end\n"); end: if (ec->global_lock) acpi_release_global_lock(glk); @@ -445,7 +443,7 @@ int ec_transaction(u8 command, EXPORT_SYMBOL(ec_transaction); -static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 * data) +static int acpi_ec_query(struct acpi_ec *ec, u8 * data) { int result; u8 d; @@ -454,16 +452,20 @@ static int acpi_ec_query_unlocked(struct acpi_ec *ec, u8 * data) .wlen = 0, .rlen = 1}; if (!ec || !data) return -EINVAL; + /* * 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). */ - result = acpi_ec_transaction_unlocked(ec, &t); + + result = acpi_ec_transaction(ec, &t); if (result) return result; + if (!d) return -ENODATA; + *data = d; return 0; } @@ -507,79 +509,43 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit) EXPORT_SYMBOL_GPL(acpi_ec_remove_query_handler); -static void acpi_ec_run(void *cxt) -{ - struct acpi_ec_query_handler *handler = cxt; - if (!handler) - return; - pr_debug(PREFIX "start query execution\n"); - if (handler->func) - handler->func(handler->data); - else if (handler->handle) - acpi_evaluate_object(handler->handle, NULL, NULL, NULL); - pr_debug(PREFIX "stop query execution\n"); - kfree(handler); -} - -static int acpi_ec_sync_query(struct acpi_ec *ec) +static void acpi_ec_gpe_query(void *ec_cxt) { + struct acpi_ec *ec = ec_cxt; u8 value = 0; - int status; - struct acpi_ec_query_handler *handler, *copy; - if ((status = acpi_ec_query_unlocked(ec, &value))) - return status; + struct acpi_ec_query_handler *handler, copy; + + if (!ec || acpi_ec_query(ec, &value)) + return; + mutex_lock(&ec->lock); list_for_each_entry(handler, &ec->list, node) { if (value == handler->query_bit) { /* have custom handler for this bit */ - copy = kmalloc(sizeof(*handler), GFP_KERNEL); - if (!copy) - return -ENOMEM; - memcpy(copy, handler, sizeof(*copy)); - pr_debug(PREFIX "push query execution (0x%2x) on queue\n", value); - return acpi_os_execute((copy->func) ? - OSL_NOTIFY_HANDLER : OSL_GPE_HANDLER, - acpi_ec_run, copy); + memcpy(©, handler, sizeof(copy)); + mutex_unlock(&ec->lock); + if (copy.func) { + copy.func(copy.data); + } else if (copy.handle) { + acpi_evaluate_object(copy.handle, NULL, NULL, NULL); + } + return; } } - return 0; -} - -static void acpi_ec_gpe_query(void *ec_cxt) -{ - struct acpi_ec *ec = ec_cxt; - if (!ec) - return; - mutex_lock(&ec->lock); - acpi_ec_sync_query(ec); mutex_unlock(&ec->lock); } -static void acpi_ec_gpe_query(void *ec_cxt); - -static int ec_check_sci(struct acpi_ec *ec, u8 state) -{ - if (state & ACPI_EC_FLAG_SCI) { - if (!test_and_set_bit(EC_FLAGS_QUERY_PENDING, &ec->flags)) { - pr_debug(PREFIX "push gpe query to the queue\n"); - return acpi_os_execute(OSL_NOTIFY_HANDLER, - acpi_ec_gpe_query, ec); - } - } - return 0; -} - static u32 acpi_ec_gpe_handler(void *data) { struct acpi_ec *ec = data; + u8 status; pr_debug(PREFIX "~~~> interrupt\n"); + status = acpi_ec_read_status(ec); - advance_transaction(ec, acpi_ec_read_status(ec)); - if (ec_transaction_done(ec) && - (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) { + advance_transaction(ec, status); + if (ec_transaction_done(ec) && (status & ACPI_EC_FLAG_IBF) == 0) wake_up(&ec->wait); - ec_check_sci(ec, acpi_ec_read_status(ec)); - } + ec_check_sci(ec, status); return ACPI_INTERRUPT_HANDLED; } diff --git a/trunk/drivers/acpi/pci_link.c b/trunk/drivers/acpi/pci_link.c index 04b0f007c9b7..394ae89409c2 100644 --- a/trunk/drivers/acpi/pci_link.c +++ b/trunk/drivers/acpi/pci_link.c @@ -56,7 +56,7 @@ ACPI_MODULE_NAME("pci_link"); static int acpi_pci_link_add(struct acpi_device *device); static int acpi_pci_link_remove(struct acpi_device *device, int type); -static const struct acpi_device_id link_device_ids[] = { +static struct acpi_device_id link_device_ids[] = { {"PNP0C0F", 0}, {"", 0}, }; diff --git a/trunk/drivers/acpi/pci_root.c b/trunk/drivers/acpi/pci_root.c index 64f55b6db73c..101cce3681d1 100644 --- a/trunk/drivers/acpi/pci_root.c +++ b/trunk/drivers/acpi/pci_root.c @@ -46,7 +46,7 @@ static int acpi_pci_root_add(struct acpi_device *device); static int acpi_pci_root_remove(struct acpi_device *device, int type); static int acpi_pci_root_start(struct acpi_device *device); -static const struct acpi_device_id root_device_ids[] = { +static struct acpi_device_id root_device_ids[] = { {"PNP0A03", 0}, {"", 0}, }; diff --git a/trunk/drivers/acpi/power.c b/trunk/drivers/acpi/power.c index 0f30c3c1eea4..22b297916519 100644 --- a/trunk/drivers/acpi/power.c +++ b/trunk/drivers/acpi/power.c @@ -65,7 +65,7 @@ static int acpi_power_remove(struct acpi_device *device, int type); static int acpi_power_resume(struct acpi_device *device); static int acpi_power_open_fs(struct inode *inode, struct file *file); -static const struct acpi_device_id power_device_ids[] = { +static struct acpi_device_id power_device_ids[] = { {ACPI_POWER_HID, 0}, {"", 0}, }; diff --git a/trunk/drivers/acpi/power_meter.c b/trunk/drivers/acpi/power_meter.c index dc4ffadf8122..2ef7030a0c28 100644 --- a/trunk/drivers/acpi/power_meter.c +++ b/trunk/drivers/acpi/power_meter.c @@ -64,7 +64,7 @@ static int can_cap_in_hardware(void) return force_cap_on || cap_in_hardware; } -static const struct acpi_device_id power_meter_ids[] = { +static struct acpi_device_id power_meter_ids[] = { {"ACPI000D", 0}, {"", 0}, }; @@ -534,7 +534,6 @@ static void remove_domain_devices(struct acpi_power_meter_resource *resource) kfree(resource->domain_devices); kobject_put(resource->holders_dir); - resource->num_domain_devices = 0; } static int read_domain_devices(struct acpi_power_meter_resource *resource) @@ -741,6 +740,7 @@ static int setup_attrs(struct acpi_power_meter_resource *resource) return res; error: + remove_domain_devices(resource); remove_attrs(resource); return res; } diff --git a/trunk/drivers/acpi/processor_idle.c b/trunk/drivers/acpi/processor_idle.c index 7c0441f63b39..d1676b1754d9 100644 --- a/trunk/drivers/acpi/processor_idle.c +++ b/trunk/drivers/acpi/processor_idle.c @@ -305,28 +305,6 @@ static int acpi_processor_get_power_info_fadt(struct acpi_processor *pr) pr->power.states[ACPI_STATE_C2].latency = acpi_gbl_FADT.C2latency; pr->power.states[ACPI_STATE_C3].latency = acpi_gbl_FADT.C3latency; - /* - * FADT specified C2 latency must be less than or equal to - * 100 microseconds. - */ - if (acpi_gbl_FADT.C2latency > ACPI_PROCESSOR_MAX_C2_LATENCY) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "C2 latency too large [%d]\n", acpi_gbl_FADT.C2latency)); - /* invalidate C2 */ - pr->power.states[ACPI_STATE_C2].address = 0; - } - - /* - * FADT supplied C3 latency must be less than or equal to - * 1000 microseconds. - */ - if (acpi_gbl_FADT.C3latency > ACPI_PROCESSOR_MAX_C3_LATENCY) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "C3 latency too large [%d]\n", acpi_gbl_FADT.C3latency)); - /* invalidate C3 */ - pr->power.states[ACPI_STATE_C3].address = 0; - } - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "lvl2[0x%08x] lvl3[0x%08x]\n", pr->power.states[ACPI_STATE_C2].address, @@ -516,6 +494,33 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr) return status; } +static void acpi_processor_power_verify_c2(struct acpi_processor_cx *cx) +{ + + if (!cx->address) + return; + + /* + * C2 latency must be less than or equal to 100 + * microseconds. + */ + else if (cx->latency > ACPI_PROCESSOR_MAX_C2_LATENCY) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "latency too large [%d]\n", cx->latency)); + return; + } + + /* + * Otherwise we've met all of our C2 requirements. + * Normalize the C2 latency to expidite policy + */ + cx->valid = 1; + + cx->latency_ticks = cx->latency; + + return; +} + static void acpi_processor_power_verify_c3(struct acpi_processor *pr, struct acpi_processor_cx *cx) { @@ -526,6 +531,16 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr, if (!cx->address) return; + /* + * C3 latency must be less than or equal to 1000 + * microseconds. + */ + else if (cx->latency > ACPI_PROCESSOR_MAX_C3_LATENCY) { + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "latency too large [%d]\n", cx->latency)); + return; + } + /* * PIIX4 Erratum #18: We don't support C3 when Type-F (fast) * DMA transfers are used by any ISA device to avoid livelock. @@ -614,10 +629,7 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) break; case ACPI_STATE_C2: - if (!cx->address) - break; - cx->valid = 1; - cx->latency_ticks = cx->latency; /* Normalize latency */ + acpi_processor_power_verify_c2(cx); break; case ACPI_STATE_C3: diff --git a/trunk/drivers/acpi/processor_pdc.c b/trunk/drivers/acpi/processor_pdc.c index 7d4ee394d0b3..f3364371207e 100644 --- a/trunk/drivers/acpi/processor_pdc.c +++ b/trunk/drivers/acpi/processor_pdc.c @@ -144,6 +144,29 @@ void acpi_processor_set_pdc(acpi_handle handle) } EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); +static int early_pdc_optin; +static int set_early_pdc_optin(const struct dmi_system_id *id) +{ + early_pdc_optin = 1; + return 0; +} + +static struct dmi_system_id __cpuinitdata early_pdc_optin_table[] = { + { + set_early_pdc_optin, "HP Envy", { + DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Envy") }, NULL}, + { + set_early_pdc_optin, "HP Pavilion dv6", { + DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv6") }, NULL}, + { + set_early_pdc_optin, "HP Pavilion dv7", { + DMI_MATCH(DMI_BIOS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv7") }, NULL}, + {}, +}; + static acpi_status early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) { @@ -151,7 +174,7 @@ early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) return AE_OK; } -void __init acpi_early_processor_set_pdc(void) +void acpi_early_processor_set_pdc(void) { /* * Check whether the system is DMI table. If yes, OSPM @@ -159,6 +182,13 @@ void __init acpi_early_processor_set_pdc(void) */ dmi_check_system(processor_idle_dmi_table); + /* + * Allow systems to opt-in to early _PDC evaluation. + */ + dmi_check_system(early_pdc_optin_table); + if (!early_pdc_optin) + return; + acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, early_init_pdc, NULL, NULL, NULL); diff --git a/trunk/drivers/acpi/processor_thermal.c b/trunk/drivers/acpi/processor_thermal.c index 6deafb4aa0da..140c5c5b423c 100644 --- a/trunk/drivers/acpi/processor_thermal.c +++ b/trunk/drivers/acpi/processor_thermal.c @@ -443,7 +443,8 @@ struct thermal_cooling_device_ops processor_cooling_ops = { #ifdef CONFIG_ACPI_PROCFS static int acpi_processor_limit_seq_show(struct seq_file *seq, void *offset) { - struct acpi_processor *pr = seq->private; + struct acpi_processor *pr = (struct acpi_processor *)seq->private; + if (!pr) goto end; diff --git a/trunk/drivers/acpi/sbs.c b/trunk/drivers/acpi/sbs.c index b16ddbf23a9c..52b9db8afc20 100644 --- a/trunk/drivers/acpi/sbs.c +++ b/trunk/drivers/acpi/sbs.c @@ -822,10 +822,7 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) static void acpi_battery_remove(struct acpi_sbs *sbs, int id) { -#if defined(CONFIG_ACPI_SYSFS_POWER) || defined(CONFIG_ACPI_PROCFS_POWER) struct acpi_battery *battery = &sbs->battery[id]; -#endif - #ifdef CONFIG_ACPI_SYSFS_POWER if (battery->bat.dev) { if (battery->have_sysfs_alarm) diff --git a/trunk/drivers/acpi/sbshc.c b/trunk/drivers/acpi/sbshc.c index fd09229282ea..d9339806df45 100644 --- a/trunk/drivers/acpi/sbshc.c +++ b/trunk/drivers/acpi/sbshc.c @@ -242,7 +242,7 @@ static int smbus_alarm(void *context) case ACPI_SBS_CHARGER: case ACPI_SBS_MANAGER: case ACPI_SBS_BATTERY: - acpi_os_execute(OSL_NOTIFY_HANDLER, + acpi_os_execute(OSL_GPE_HANDLER, acpi_smbus_callback, hc); default:; } diff --git a/trunk/drivers/acpi/video.c b/trunk/drivers/acpi/video.c index b765790b32be..72e76b4b6538 100644 --- a/trunk/drivers/acpi/video.c +++ b/trunk/drivers/acpi/video.c @@ -78,13 +78,6 @@ MODULE_LICENSE("GPL"); static int brightness_switch_enabled = 1; module_param(brightness_switch_enabled, bool, 0644); -/* - * By default, we don't allow duplicate ACPI video bus devices - * under the same VGA controller - */ -static int allow_duplicates; -module_param(allow_duplicates, bool, 0644); - static int register_count = 0; static int acpi_video_bus_add(struct acpi_device *device); static int acpi_video_bus_remove(struct acpi_device *device, int type); @@ -2246,47 +2239,11 @@ static int acpi_video_resume(struct acpi_device *device) return AE_OK; } -static acpi_status -acpi_video_bus_match(acpi_handle handle, u32 level, void *context, - void **return_value) -{ - struct acpi_device *device = context; - struct acpi_device *sibling; - int result; - - if (handle == device->handle) - return AE_CTRL_TERMINATE; - - result = acpi_bus_get_device(handle, &sibling); - if (result) - return AE_OK; - - if (!strcmp(acpi_device_name(sibling), ACPI_VIDEO_BUS_NAME)) - return AE_ALREADY_EXISTS; - - return AE_OK; -} - static int acpi_video_bus_add(struct acpi_device *device) { struct acpi_video_bus *video; struct input_dev *input; int error; - acpi_status status; - - status = acpi_walk_namespace(ACPI_TYPE_DEVICE, - device->parent->handle, 1, - acpi_video_bus_match, NULL, - device, NULL); - if (status == AE_ALREADY_EXISTS) { - printk(KERN_WARNING FW_BUG - "Duplicate ACPI video bus devices for the" - " same VGA controller, please try module " - "parameter \"video.allow_duplicates=1\"" - "if the current driver doesn't work.\n"); - if (!allow_duplicates) - return -ENODEV; - } video = kzalloc(sizeof(struct acpi_video_bus), GFP_KERNEL); if (!video) diff --git a/trunk/drivers/platform/x86/Kconfig b/trunk/drivers/platform/x86/Kconfig index f526e735c5ab..db32c25e3605 100644 --- a/trunk/drivers/platform/x86/Kconfig +++ b/trunk/drivers/platform/x86/Kconfig @@ -364,7 +364,6 @@ config EEEPC_LAPTOP select HWMON select LEDS_CLASS select NEW_LEDS - select INPUT_SPARSEKMAP ---help--- This driver supports the Fn-Fx keys on Eee PC laptops. diff --git a/trunk/drivers/platform/x86/eeepc-laptop.c b/trunk/drivers/platform/x86/eeepc-laptop.c index e2be6bb33d92..5838c69b2fb3 100644 --- a/trunk/drivers/platform/x86/eeepc-laptop.c +++ b/trunk/drivers/platform/x86/eeepc-laptop.c @@ -31,12 +31,10 @@ #include #include #include -#include #include #include #include #include -#include #define EEEPC_LAPTOP_VERSION "0.1" #define EEEPC_LAPTOP_NAME "Eee PC Hotkey Driver" @@ -50,14 +48,6 @@ MODULE_AUTHOR("Corentin Chary, Eric Cooper"); MODULE_DESCRIPTION(EEEPC_LAPTOP_NAME); MODULE_LICENSE("GPL"); -static bool hotplug_disabled; - -module_param(hotplug_disabled, bool, 0644); -MODULE_PARM_DESC(hotplug_disabled, - "Disable hotplug for wireless device. " - "If your laptop need that, please report to " - "acpi4asus-user@lists.sourceforge.net."); - /* * Definitions for Asus EeePC */ @@ -130,28 +120,38 @@ static const char *cm_setv[] = { NULL, NULL, "PBPS", "TPDS" }; +struct key_entry { + char type; + u8 code; + u16 keycode; +}; + +enum { KE_KEY, KE_END }; + static const struct key_entry eeepc_keymap[] = { - { KE_KEY, 0x10, { KEY_WLAN } }, - { KE_KEY, 0x11, { KEY_WLAN } }, - { KE_KEY, 0x12, { KEY_PROG1 } }, - { KE_KEY, 0x13, { KEY_MUTE } }, - { KE_KEY, 0x14, { KEY_VOLUMEDOWN } }, - { KE_KEY, 0x15, { KEY_VOLUMEUP } }, - { KE_KEY, 0x16, { KEY_DISPLAY_OFF } }, - { KE_KEY, 0x1a, { KEY_COFFEE } }, - { KE_KEY, 0x1b, { KEY_ZOOM } }, - { KE_KEY, 0x1c, { KEY_PROG2 } }, - { KE_KEY, 0x1d, { KEY_PROG3 } }, - { KE_KEY, NOTIFY_BRN_MIN, { KEY_BRIGHTNESSDOWN } }, - { KE_KEY, NOTIFY_BRN_MAX, { KEY_BRIGHTNESSUP } }, - { KE_KEY, 0x30, { KEY_SWITCHVIDEOMODE } }, - { KE_KEY, 0x31, { KEY_SWITCHVIDEOMODE } }, - { KE_KEY, 0x32, { KEY_SWITCHVIDEOMODE } }, - { KE_KEY, 0x37, { KEY_F13 } }, /* Disable Touchpad */ - { KE_KEY, 0x38, { KEY_F14 } }, - { KE_END, 0 }, + /* Sleep already handled via generic ACPI code */ + {KE_KEY, 0x10, KEY_WLAN }, + {KE_KEY, 0x11, KEY_WLAN }, + {KE_KEY, 0x12, KEY_PROG1 }, + {KE_KEY, 0x13, KEY_MUTE }, + {KE_KEY, 0x14, KEY_VOLUMEDOWN }, + {KE_KEY, 0x15, KEY_VOLUMEUP }, + {KE_KEY, 0x16, KEY_DISPLAY_OFF }, + {KE_KEY, 0x1a, KEY_COFFEE }, + {KE_KEY, 0x1b, KEY_ZOOM }, + {KE_KEY, 0x1c, KEY_PROG2 }, + {KE_KEY, 0x1d, KEY_PROG3 }, + {KE_KEY, NOTIFY_BRN_MIN, KEY_BRIGHTNESSDOWN }, + {KE_KEY, NOTIFY_BRN_MAX, KEY_BRIGHTNESSUP }, + {KE_KEY, 0x30, KEY_SWITCHVIDEOMODE }, + {KE_KEY, 0x31, KEY_SWITCHVIDEOMODE }, + {KE_KEY, 0x32, KEY_SWITCHVIDEOMODE }, + {KE_KEY, 0x37, KEY_F13 }, /* Disable Touchpad */ + {KE_KEY, 0x38, KEY_F14 }, + {KE_END, 0}, }; + /* * This is the main structure, we can use it to store useful information */ @@ -159,8 +159,6 @@ struct eeepc_laptop { acpi_handle handle; /* the handle of the acpi device */ u32 cm_supported; /* the control methods supported by this BIOS */ - bool cpufv_disabled; - bool hotplug_disabled; u16 event_count[128]; /* count for each event */ struct platform_device *platform_device; @@ -380,8 +378,6 @@ static ssize_t store_cpufv(struct device *dev, struct eeepc_cpufv c; int rv, value; - if (eeepc->cpufv_disabled) - return -EPERM; if (get_cpufv(eeepc, &c)) return -ENODEV; rv = parse_arg(buf, count, &value); @@ -393,41 +389,6 @@ static ssize_t store_cpufv(struct device *dev, return rv; } -static ssize_t show_cpufv_disabled(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct eeepc_laptop *eeepc = dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", eeepc->cpufv_disabled); -} - -static ssize_t store_cpufv_disabled(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct eeepc_laptop *eeepc = dev_get_drvdata(dev); - int rv, value; - - rv = parse_arg(buf, count, &value); - if (rv < 0) - return rv; - - switch (value) { - case 0: - if (eeepc->cpufv_disabled) - pr_warning("cpufv enabled (not officially supported " - "on this model)\n"); - eeepc->cpufv_disabled = false; - return rv; - case 1: - return -EPERM; - default: - return -EINVAL; - } -} - - static struct device_attribute dev_attr_cpufv = { .attr = { .name = "cpufv", @@ -443,22 +404,12 @@ static struct device_attribute dev_attr_available_cpufv = { .show = show_available_cpufv }; -static struct device_attribute dev_attr_cpufv_disabled = { - .attr = { - .name = "cpufv_disabled", - .mode = 0644 }, - .show = show_cpufv_disabled, - .store = store_cpufv_disabled -}; - - static struct attribute *platform_attributes[] = { &dev_attr_camera.attr, &dev_attr_cardr.attr, &dev_attr_disp.attr, &dev_attr_cpufv.attr, &dev_attr_available_cpufv.attr, - &dev_attr_cpufv_disabled.attr, NULL }; @@ -845,9 +796,6 @@ static int eeepc_rfkill_init(struct eeepc_laptop *eeepc) if (result && result != -ENODEV) goto exit; - if (eeepc->hotplug_disabled) - return 0; - result = eeepc_setup_pci_hotplug(eeepc); /* * If we get -EBUSY then something else is handling the PCI hotplug - @@ -1142,42 +1090,120 @@ static void eeepc_backlight_exit(struct eeepc_laptop *eeepc) /* * Input device (i.e. hotkeys) */ -static int eeepc_input_init(struct eeepc_laptop *eeepc) +static struct key_entry *eeepc_get_entry_by_scancode( + struct eeepc_laptop *eeepc, + int code) { - struct input_dev *input; - int error; + struct key_entry *key; - input = input_allocate_device(); - if (!input) { - pr_info("Unable to allocate input device\n"); - return -ENOMEM; + for (key = eeepc->keymap; key->type != KE_END; key++) + if (code == key->code) + return key; + + return NULL; +} + +static void eeepc_input_notify(struct eeepc_laptop *eeepc, int event) +{ + static struct key_entry *key; + + key = eeepc_get_entry_by_scancode(eeepc, event); + if (key) { + switch (key->type) { + case KE_KEY: + input_report_key(eeepc->inputdev, key->keycode, + 1); + input_sync(eeepc->inputdev); + input_report_key(eeepc->inputdev, key->keycode, + 0); + input_sync(eeepc->inputdev); + break; + } } +} + +static struct key_entry *eeepc_get_entry_by_keycode( + struct eeepc_laptop *eeepc, int code) +{ + struct key_entry *key; + + for (key = eeepc->keymap; key->type != KE_END; key++) + if (code == key->keycode && key->type == KE_KEY) + return key; - input->name = "Asus EeePC extra buttons"; - input->phys = EEEPC_LAPTOP_FILE "/input0"; - input->id.bustype = BUS_HOST; - input->dev.parent = &eeepc->platform_device->dev; + return NULL; +} - error = sparse_keymap_setup(input, eeepc_keymap, NULL); - if (error) { - pr_err("Unable to setup input device keymap\n"); - goto err_free_dev; +static int eeepc_getkeycode(struct input_dev *dev, int scancode, int *keycode) +{ + struct eeepc_laptop *eeepc = input_get_drvdata(dev); + struct key_entry *key = eeepc_get_entry_by_scancode(eeepc, scancode); + + if (key && key->type == KE_KEY) { + *keycode = key->keycode; + return 0; } - error = input_register_device(input); - if (error) { - pr_err("Unable to register input device\n"); - goto err_free_keymap; + return -EINVAL; +} + +static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode) +{ + struct eeepc_laptop *eeepc = input_get_drvdata(dev); + struct key_entry *key; + int old_keycode; + + if (keycode < 0 || keycode > KEY_MAX) + return -EINVAL; + + key = eeepc_get_entry_by_scancode(eeepc, scancode); + if (key && key->type == KE_KEY) { + old_keycode = key->keycode; + key->keycode = keycode; + set_bit(keycode, dev->keybit); + if (!eeepc_get_entry_by_keycode(eeepc, old_keycode)) + clear_bit(old_keycode, dev->keybit); + return 0; } - eeepc->inputdev = input; - return 0; + return -EINVAL; +} - err_free_keymap: - sparse_keymap_free(input); - err_free_dev: - input_free_device(input); - return error; +static int eeepc_input_init(struct eeepc_laptop *eeepc) +{ + const struct key_entry *key; + int result; + + eeepc->inputdev = input_allocate_device(); + if (!eeepc->inputdev) { + pr_info("Unable to allocate input device\n"); + return -ENOMEM; + } + eeepc->inputdev->name = "Asus EeePC extra buttons"; + eeepc->inputdev->dev.parent = &eeepc->platform_device->dev; + eeepc->inputdev->phys = EEEPC_LAPTOP_FILE "/input0"; + eeepc->inputdev->id.bustype = BUS_HOST; + eeepc->inputdev->getkeycode = eeepc_getkeycode; + eeepc->inputdev->setkeycode = eeepc_setkeycode; + input_set_drvdata(eeepc->inputdev, eeepc); + + eeepc->keymap = kmemdup(eeepc_keymap, sizeof(eeepc_keymap), + GFP_KERNEL); + for (key = eeepc_keymap; key->type != KE_END; key++) { + switch (key->type) { + case KE_KEY: + set_bit(EV_KEY, eeepc->inputdev->evbit); + set_bit(key->keycode, eeepc->inputdev->keybit); + break; + } + } + result = input_register_device(eeepc->inputdev); + if (result) { + pr_info("Unable to register input device\n"); + input_free_device(eeepc->inputdev); + return result; + } + return 0; } static void eeepc_input_exit(struct eeepc_laptop *eeepc) @@ -1227,59 +1253,11 @@ static void eeepc_acpi_notify(struct acpi_device *device, u32 event) * event will be desired value (or else ignored) */ } - sparse_keymap_report_event(eeepc->inputdev, event, - 1, true); + eeepc_input_notify(eeepc, event); } } else { /* Everything else is a bona-fide keypress event */ - sparse_keymap_report_event(eeepc->inputdev, event, 1, true); - } -} - -static void eeepc_dmi_check(struct eeepc_laptop *eeepc) -{ - const char *model; - - model = dmi_get_system_info(DMI_PRODUCT_NAME); - if (!model) - return; - - /* - * Blacklist for setting cpufv (cpu speed). - * - * EeePC 4G ("701") implements CFVS, but it is not supported - * by the pre-installed OS, and the original option to change it - * in the BIOS setup screen was removed in later versions. - * - * Judging by the lack of "Super Hybrid Engine" on Asus product pages, - * this applies to all "701" models (4G/4G Surf/2G Surf). - * - * So Asus made a deliberate decision not to support it on this model. - * We have several reports that using it can cause the system to hang - * - * The hang has also been reported on a "702" (Model name "8G"?). - * - * We avoid dmi_check_system() / dmi_match(), because they use - * substring matching. We don't want to affect the "701SD" - * and "701SDX" models, because they do support S.H.E. - */ - if (strcmp(model, "701") == 0 || strcmp(model, "702") == 0) { - eeepc->cpufv_disabled = true; - pr_info("model %s does not officially support setting cpu " - "speed\n", model); - pr_info("cpufv disabled to avoid instability\n"); - } - - /* - * Blacklist for wlan hotplug - * - * Eeepc 1005HA doesn't work like others models and don't need the - * hotplug code. In fact, current hotplug code seems to unplug another - * device... - */ - if (strcmp(model, "1005HA") == 0 || strcmp(model, "1201N") == 0) { - eeepc->hotplug_disabled = true; - pr_info("wlan hotplug disabled\n"); + eeepc_input_notify(eeepc, event); } } @@ -1364,10 +1342,6 @@ static int __devinit eeepc_acpi_add(struct acpi_device *device) strcpy(acpi_device_class(device), EEEPC_ACPI_CLASS); device->driver_data = eeepc; - eeepc->hotplug_disabled = hotplug_disabled; - - eeepc_dmi_check(eeepc); - result = eeepc_acpi_init(eeepc, device); if (result) goto fail_platform; @@ -1478,12 +1452,10 @@ static int __init eeepc_laptop_init(void) result = acpi_bus_register_driver(&eeepc_acpi_driver); if (result < 0) goto fail_acpi_driver; - if (!eeepc_device_present) { result = -ENODEV; goto fail_no_device; } - return 0; fail_no_device: diff --git a/trunk/drivers/platform/x86/sony-laptop.c b/trunk/drivers/platform/x86/sony-laptop.c index 3f71a605a492..5af53340da6f 100644 --- a/trunk/drivers/platform/x86/sony-laptop.c +++ b/trunk/drivers/platform/x86/sony-laptop.c @@ -1201,12 +1201,9 @@ static void sony_nc_rfkill_setup(struct acpi_device *device) /* the buffer is filled with magic numbers describing the devices * available, 0xff terminates the enumeration */ - for (i = 0; i < device_enum->buffer.length; i++) { - - dev_code = *(device_enum->buffer.pointer + i); - if (dev_code == 0xff) - break; - + while ((dev_code = *(device_enum->buffer.pointer + i)) != 0xff && + i < device_enum->buffer.length) { + i++; dprintk("Radio devices, looking at 0x%.2x\n", dev_code); if (dev_code == 0 && !sony_rfkill_devices[SONY_WIFI]) diff --git a/trunk/include/acpi/platform/aclinux.h b/trunk/include/acpi/platform/aclinux.h index 09469971472f..9d7febde10a1 100644 --- a/trunk/include/acpi/platform/aclinux.h +++ b/trunk/include/acpi/platform/aclinux.h @@ -152,7 +152,7 @@ static inline void *acpi_os_acquire_object(acpi_cache_t * cache) #include #define ACPI_PREEMPTION_POINT() \ do { \ - if (!in_atomic_preempt_off() && !irqs_disabled()) \ + if (!in_atomic_preempt_off()) \ cond_resched(); \ } while (0) diff --git a/trunk/include/linux/acpi.h b/trunk/include/linux/acpi.h index b926afe8c03e..36924255c0d5 100644 --- a/trunk/include/linux/acpi.h +++ b/trunk/include/linux/acpi.h @@ -80,7 +80,7 @@ char * __acpi_map_table (unsigned long phys_addr, unsigned long size); void __acpi_unmap_table(char *map, unsigned long size); int early_acpi_boot_init(void); int acpi_boot_init (void); -void acpi_boot_table_init (void); +int acpi_boot_table_init (void); int acpi_mps_check (void); int acpi_numa_init (void); @@ -321,9 +321,9 @@ static inline int acpi_boot_init(void) return 0; } -static inline void acpi_boot_table_init(void) +static inline int acpi_boot_table_init(void) { - return; + return 0; } static inline int acpi_mps_check(void)