aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorHenrique de Moraes Holschuh <hmh@hmh.eng.br>2008-10-18 13:23:52 -0400
committerLen Brown <len.brown@intel.com>2008-10-22 18:13:10 -0400
commit75700e53cd14ccc7a5a42547497dff11fe209186 (patch)
tree33f4793b259d53147fe8c1064fd5470561ce6277 /drivers
parent3fa8749e584b55f1180411ab1b51117190bac1e5 (diff)
ACPI: thinkpad-acpi: attempt to preserve fan state on resume
Attempt to preserve fan state across sleep and hibernation if the fan control mode is enabled. For safety reasons, only the PWM OFF (fan at 100%) or maximum closed-loop level (level 7) are preserved. If the fan state was set to anything else, it will not be restored. Also, should the fan be at PWM OFF mode at resume, it will be left at that state (but this is extremely unlikely, no ThinkPad firmware was ever reported to do this). For reference, the known states used for fan control upon resume by the firmware are either "auto" or "level 7" depending on whether the laptop wakes due to normal conditions or a thermal emergency. Fixes: http://bugzilla.kernel.org/show_bug.cgi?id=11331 Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br> Cc: Richard Hartmann <richih.mailinglist@gmail.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/misc/thinkpad_acpi.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c
index 6b9300779a43..1dcf0660d8b5 100644
--- a/drivers/misc/thinkpad_acpi.c
+++ b/drivers/misc/thinkpad_acpi.c
@@ -5983,6 +5983,52 @@ static void fan_exit(void)
5983 flush_workqueue(tpacpi_wq); 5983 flush_workqueue(tpacpi_wq);
5984} 5984}
5985 5985
5986static void fan_suspend(pm_message_t state)
5987{
5988 if (!fan_control_allowed)
5989 return;
5990
5991 /* Store fan status in cache */
5992 fan_get_status_safe(NULL);
5993 if (tp_features.fan_ctrl_status_undef)
5994 fan_control_desired_level = TP_EC_FAN_AUTO;
5995}
5996
5997static void fan_resume(void)
5998{
5999 u8 saved_fan_level;
6000 u8 current_level = 7;
6001 bool do_set = false;
6002
6003 /* DSDT *always* updates status on resume */
6004 tp_features.fan_ctrl_status_undef = 0;
6005
6006 saved_fan_level = fan_control_desired_level;
6007 if (!fan_control_allowed ||
6008 (fan_get_status_safe(&current_level) < 0))
6009 return;
6010
6011 switch (fan_control_access_mode) {
6012 case TPACPI_FAN_WR_ACPI_SFAN:
6013 do_set = (saved_fan_level > current_level);
6014 break;
6015 case TPACPI_FAN_WR_ACPI_FANS:
6016 case TPACPI_FAN_WR_TPEC:
6017 do_set = ((saved_fan_level & TP_EC_FAN_FULLSPEED) ||
6018 (saved_fan_level == 7 &&
6019 !(current_level & TP_EC_FAN_FULLSPEED)));
6020 break;
6021 default:
6022 return;
6023 }
6024 if (do_set) {
6025 printk(TPACPI_NOTICE
6026 "restoring fan level to 0x%02x\n",
6027 saved_fan_level);
6028 fan_set_level_safe(saved_fan_level);
6029 }
6030}
6031
5986static int fan_read(char *p) 6032static int fan_read(char *p)
5987{ 6033{
5988 int len = 0; 6034 int len = 0;
@@ -6174,6 +6220,8 @@ static struct ibm_struct fan_driver_data = {
6174 .read = fan_read, 6220 .read = fan_read,
6175 .write = fan_write, 6221 .write = fan_write,
6176 .exit = fan_exit, 6222 .exit = fan_exit,
6223 .suspend = fan_suspend,
6224 .resume = fan_resume,
6177}; 6225};
6178 6226
6179/**************************************************************************** 6227/****************************************************************************