From 30b358f8908cc65dd150e36b55adc1927ad3e338 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Fri, 16 Jan 2009 12:53:42 -0500 Subject: [PATCH] --- yaml --- r: 129870 b: refs/heads/master c: 0e4240d94628530a912d216cad1e32d2e3827327 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/drivers/acpi/ec.c | 73 +++++++++++++++++++++--------------- trunk/drivers/acpi/thermal.c | 16 ++++++-- 3 files changed, 56 insertions(+), 35 deletions(-) diff --git a/[refs] b/[refs] index 4838814b7c5a..b2c08e474769 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: c6cb0e878446c79f42e7833d7bb69ed6bfbb381f +refs/heads/master: 0e4240d94628530a912d216cad1e32d2e3827327 diff --git a/trunk/drivers/acpi/ec.c b/trunk/drivers/acpi/ec.c index a2b82c90a683..8dfcbb8aff73 100644 --- a/trunk/drivers/acpi/ec.c +++ b/trunk/drivers/acpi/ec.c @@ -120,6 +120,31 @@ static struct acpi_ec { spinlock_t curr_lock; } *boot_ec, *first_ec; +/* + * Some Asus system have exchanged ECDT data/command IO addresses. + */ +static int print_ecdt_error(const struct dmi_system_id *id) +{ + printk(KERN_NOTICE PREFIX "%s detected - " + "ECDT has exchanged control/data I/O address\n", + id->ident); + return 0; +} + +static struct dmi_system_id __cpuinitdata ec_dmi_table[] = { + { + print_ecdt_error, "Asus L4R", { + DMI_MATCH(DMI_BIOS_VERSION, "1008.006"), + DMI_MATCH(DMI_PRODUCT_NAME, "L4R"), + DMI_MATCH(DMI_BOARD_NAME, "L4R") }, NULL}, + { + print_ecdt_error, "Asus M6R", { + DMI_MATCH(DMI_BIOS_VERSION, "0207"), + DMI_MATCH(DMI_PRODUCT_NAME, "M6R"), + DMI_MATCH(DMI_BOARD_NAME, "M6R") }, NULL}, + {}, +}; + /* -------------------------------------------------------------------------- Transaction Management -------------------------------------------------------------------------- */ @@ -958,8 +983,8 @@ static const struct acpi_device_id ec_device_ids[] = { int __init acpi_ec_ecdt_probe(void) { acpi_status status; - struct acpi_ec *saved_ec = NULL; struct acpi_table_ecdt *ecdt_ptr; + acpi_handle dummy; boot_ec = make_acpi_ec(); if (!boot_ec) @@ -973,16 +998,21 @@ int __init acpi_ec_ecdt_probe(void) pr_info(PREFIX "EC description table is found, configuring boot EC\n"); boot_ec->command_addr = ecdt_ptr->control.address; boot_ec->data_addr = ecdt_ptr->data.address; + if (dmi_check_system(ec_dmi_table)) { + /* + * If the board falls into ec_dmi_table, it means + * that ECDT table gives the incorrect command/status + * & data I/O address. Just fix it. + */ + boot_ec->data_addr = ecdt_ptr->control.address; + boot_ec->command_addr = ecdt_ptr->data.address; + } boot_ec->gpe = ecdt_ptr->gpe; boot_ec->handle = ACPI_ROOT_OBJECT; acpi_get_handle(ACPI_ROOT_OBJECT, ecdt_ptr->id, &boot_ec->handle); - /* Don't trust ECDT, which comes from ASUSTek */ - if (!dmi_name_in_vendors("ASUS")) + /* Add some basic check against completely broken table */ + if (boot_ec->data_addr != boot_ec->command_addr) goto install; - saved_ec = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); - if (!saved_ec) - return -ENOMEM; - memcpy(&saved_ec, boot_ec, sizeof(saved_ec)); /* fall through */ } /* This workaround is needed only on some broken machines, @@ -993,29 +1023,12 @@ int __init acpi_ec_ecdt_probe(void) /* Check that acpi_get_devices actually find something */ if (ACPI_FAILURE(status) || !boot_ec->handle) goto error; - if (saved_ec) { - /* try to find good ECDT from ASUSTek */ - if (saved_ec->command_addr != boot_ec->command_addr || - saved_ec->data_addr != boot_ec->data_addr || - saved_ec->gpe != boot_ec->gpe || - saved_ec->handle != boot_ec->handle) - pr_info(PREFIX "ASUSTek keeps feeding us with broken " - "ECDT tables, which are very hard to workaround. " - "Trying to use DSDT EC info instead. Please send " - "output of acpidump to linux-acpi@vger.kernel.org\n"); - kfree(saved_ec); - saved_ec = NULL; - } else { - /* We really need to limit this workaround, the only ASUS, - * which needs it, has fake EC._INI method, so use it as flag. - * Keep boot_ec struct as it will be needed soon. - */ - acpi_handle dummy; - if (!dmi_name_in_vendors("ASUS") || - ACPI_FAILURE(acpi_get_handle(boot_ec->handle, "_INI", - &dummy))) - return -ENODEV; - } + /* We really need to limit this workaround, the only ASUS, + * which needs it, has fake EC._INI method, so use it as flag. + * Keep boot_ec struct as it will be needed soon. + */ + if (ACPI_FAILURE(acpi_get_handle(boot_ec->handle, "_INI", &dummy))) + return -ENODEV; install: if (!ec_install_handlers(boot_ec)) { first_ec = boot_ec; diff --git a/trunk/drivers/acpi/thermal.c b/trunk/drivers/acpi/thermal.c index 073ff09218a9..99e6f1f8ea45 100644 --- a/trunk/drivers/acpi/thermal.c +++ b/trunk/drivers/acpi/thermal.c @@ -416,7 +416,8 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) } /* Passive (optional) */ - if (flag & ACPI_TRIPS_PASSIVE) { + if (((flag & ACPI_TRIPS_PASSIVE) && tz->trips.passive.flags.valid) || + (flag == ACPI_TRIPS_INIT)) { valid = tz->trips.passive.flags.valid; if (psv == -1) { status = AE_SUPPORT; @@ -462,8 +463,11 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) memset(&devices, 0, sizeof(struct acpi_handle_list)); status = acpi_evaluate_reference(tz->device->handle, "_PSL", NULL, &devices); - if (ACPI_FAILURE(status)) + if (ACPI_FAILURE(status)) { + printk(KERN_WARNING PREFIX + "Invalid passive threshold\n"); tz->trips.passive.flags.valid = 0; + } else tz->trips.passive.flags.valid = 1; @@ -487,7 +491,8 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) if (act == -1) break; /* disable all active trip points */ - if (flag & ACPI_TRIPS_ACTIVE) { + if ((flag == ACPI_TRIPS_INIT) || ((flag & ACPI_TRIPS_ACTIVE) && + tz->trips.active[i].flags.valid)) { status = acpi_evaluate_integer(tz->device->handle, name, NULL, &tmp); if (ACPI_FAILURE(status)) { @@ -521,8 +526,11 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag) memset(&devices, 0, sizeof(struct acpi_handle_list)); status = acpi_evaluate_reference(tz->device->handle, name, NULL, &devices); - if (ACPI_FAILURE(status)) + if (ACPI_FAILURE(status)) { + printk(KERN_WARNING PREFIX + "Invalid active%d threshold\n", i); tz->trips.active[i].flags.valid = 0; + } else tz->trips.active[i].flags.valid = 1;