X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Facpi%2Fthermal.c;h=05388672d41a03cd18737358ce23eb8a819d1664;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=7b94ac0813fa1d71184893d50a1fe070864b9a81;hpb=a2c21200f1c81b08cb55e417b68150bba439b646;p=linux-2.6.git diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index 7b94ac081..05388672d 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -60,6 +60,7 @@ #define ACPI_THERMAL_NOTIFY_HOT 0xF1 #define ACPI_THERMAL_MODE_ACTIVE 0x00 #define ACPI_THERMAL_MODE_PASSIVE 0x01 +#define ACPI_THERMAL_MODE_CRT 0xff #define ACPI_THERMAL_PATH_POWEROFF "/sbin/poweroff" #define ACPI_THERMAL_MAX_ACTIVE 10 @@ -160,6 +161,7 @@ struct acpi_thermal { unsigned long last_temperature; unsigned long polling_frequency; u8 cooling_mode; + volatile u8 zombie; struct acpi_thermal_flags flags; struct acpi_thermal_state state; struct acpi_thermal_trips trips; @@ -289,13 +291,6 @@ acpi_thermal_set_cooling_mode ( status = acpi_get_handle(tz->handle, "_SCP", &handle); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "_SCP not present\n")); - status = acpi_get_handle(tz->handle, "_PSV", &handle); - if(!ACPI_FAILURE(status)) { - tz->cooling_mode = 1; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cooling mode [%s]\n", - mode?"passive":"active")); - return_VALUE(0); - } return_VALUE(-ENODEV); } @@ -653,7 +648,10 @@ static void acpi_thermal_run ( unsigned long data) { - acpi_os_queue_for_execution(OSD_PRIORITY_GPE, acpi_thermal_check, (void *) data); + struct acpi_thermal *tz = (struct acpi_thermal *)data; + if (!tz->zombie) + acpi_os_queue_for_execution(OSD_PRIORITY_GPE, + acpi_thermal_check, (void *) data); } @@ -665,7 +663,7 @@ acpi_thermal_check ( struct acpi_thermal *tz = (struct acpi_thermal *) data; unsigned long sleep_time = 0; int i = 0; - struct acpi_thermal_state state = tz->state; + struct acpi_thermal_state state; ACPI_FUNCTION_TRACE("acpi_thermal_check"); @@ -674,6 +672,8 @@ acpi_thermal_check ( return_VOID; } + state = tz->state; + result = acpi_thermal_get_temperature(tz); if (result) return_VOID; @@ -899,8 +899,10 @@ acpi_thermal_write_trip_points ( struct seq_file *m = (struct seq_file *)file->private_data; struct acpi_thermal *tz = (struct acpi_thermal *)m->private; - char limit_string[25] = {'\0'}; - int critical, hot, passive, active0, active1; + char limit_string[65] = {'\0'}; + int num, critical, hot, passive; + int active[ACPI_THERMAL_MAX_ACTIVE]; + int i = 0; ACPI_FUNCTION_TRACE("acpi_thermal_write_trip_points"); @@ -916,7 +918,11 @@ acpi_thermal_write_trip_points ( limit_string[count] = '\0'; - if (sscanf(limit_string, "%d:%d:%d:%d:%d", &critical, &hot, &passive, &active0, &active1) != 5) { + num = sscanf(limit_string, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d", + &critical, &hot, &passive, + &active[0], &active[1], &active[2], &active[3], &active[4], + &active[5], &active[6], &active[7], &active[8], &active[9]); + if(!(num >=5 && num < (ACPI_THERMAL_MAX_ACTIVE + 3))) { ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid data format\n")); return_VALUE(-EINVAL); } @@ -924,8 +930,11 @@ acpi_thermal_write_trip_points ( tz->trips.critical.temperature = CELSIUS_TO_KELVIN(critical); tz->trips.hot.temperature = CELSIUS_TO_KELVIN(hot); tz->trips.passive.temperature = CELSIUS_TO_KELVIN(passive); - tz->trips.active[0].temperature = CELSIUS_TO_KELVIN(active0); - tz->trips.active[1].temperature = CELSIUS_TO_KELVIN(active1); + for (i = 0; i < num - 3; i++) { + if (!(tz->trips.active[i].flags.valid)) + break; + tz->trips.active[i].temperature = CELSIUS_TO_KELVIN(active[i]); + } return_VALUE(count); } @@ -941,12 +950,14 @@ static int acpi_thermal_cooling_seq_show(struct seq_file *seq, void *offset) goto end; if (!tz->flags.cooling_mode) { - seq_puts(seq, "\n"); - goto end; + seq_puts(seq, "\n"); } - seq_printf(seq, "cooling mode: %s\n", - tz->cooling_mode?"passive":"active"); + if ( tz->cooling_mode == ACPI_THERMAL_MODE_CRT ) + seq_printf(seq, "cooling mode: critical\n"); + else + seq_printf(seq, "cooling mode: %s\n", + tz->cooling_mode?"passive":"active"); end: return 0; @@ -988,6 +999,8 @@ acpi_thermal_write_cooling_mode ( if (result) return_VALUE(result); + acpi_thermal_check(tz); + return_VALUE(count); } @@ -1225,16 +1238,34 @@ acpi_thermal_get_info ( if (result) return_VALUE(result); - /* Set the cooling mode [_SCP] to active cooling (default) */ - result = acpi_thermal_set_cooling_mode(tz, ACPI_THERMAL_MODE_ACTIVE); - if (!result) - tz->flags.cooling_mode = 1; - /* Get trip points [_CRT, _PSV, etc.] (required) */ result = acpi_thermal_get_trip_points(tz); if (result) return_VALUE(result); + /* Set the cooling mode [_SCP] to active cooling (default) */ + result = acpi_thermal_set_cooling_mode(tz, ACPI_THERMAL_MODE_ACTIVE); + if (!result) + tz->flags.cooling_mode = 1; + else { + /* Oh,we have not _SCP method. + Generally show cooling_mode by _ACx, _PSV,spec 12.2*/ + tz->flags.cooling_mode = 0; + if ( tz->trips.active[0].flags.valid && tz->trips.passive.flags.valid ) { + if ( tz->trips.passive.temperature > tz->trips.active[0].temperature ) + tz->cooling_mode = ACPI_THERMAL_MODE_ACTIVE; + else + tz->cooling_mode = ACPI_THERMAL_MODE_PASSIVE; + } else if ( !tz->trips.active[0].flags.valid && tz->trips.passive.flags.valid ) { + tz->cooling_mode = ACPI_THERMAL_MODE_PASSIVE; + } else if ( tz->trips.active[0].flags.valid && !tz->trips.passive.flags.valid ) { + tz->cooling_mode = ACPI_THERMAL_MODE_ACTIVE; + } else { + /* _ACx and _PSV are optional, but _CRT is required */ + tz->cooling_mode = ACPI_THERMAL_MODE_CRT; + } + } + /* Get default polling frequency [_TZP] (optional) */ if (tzp) tz->polling_frequency = tzp; @@ -1324,8 +1355,14 @@ acpi_thermal_remove ( tz = (struct acpi_thermal *) acpi_driver_data(device); - if (timer_pending(&(tz->timer))) - del_timer(&(tz->timer)); + /* avoid timer adding new defer task */ + tz->zombie = 1; + /* wait for running timer (on other CPUs) finish */ + del_timer_sync(&(tz->timer)); + /* synchronize deferred task */ + acpi_os_wait_events_complete(NULL); + /* deferred task may reinsert timer */ + del_timer_sync(&(tz->timer)); status = acpi_remove_notify_handler(tz->handle, ACPI_DEVICE_NOTIFY, acpi_thermal_notify); @@ -1347,6 +1384,7 @@ acpi_thermal_remove ( acpi_thermal_remove_fs(device); + kfree(tz); return_VALUE(0); }