[ltp] [patch 11/11] ibm-acpi: implement fan watchdog command

Henrique de Moraes Holschuh linux-thinkpad@linux-thinkpad.org
Mon, 09 Oct 2006 09:41:42 -0300


This patch implements a fan control safety watchdog.  When the watchdog timer
expires, the equivalent action of a "fan enable" command is executed.  The
watchdog timer is reset at every reception of a fan control command that could
change the state of the fan itself.

This command is meant to be used by userspace fan control daemons, to make sure
the fan is never left set to an unsafe level because of userspace problems.

The watchdog is programmed using echo "watchdog <number>" > fan, where number
is the number of seconds to wait before doing an "enable", and zero disables
the watchdog.

Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>

---
 drivers/acpi/ibm_acpi.c |   48 ++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 40 insertions(+), 8 deletions(-)

Index: 2.6.18/drivers/acpi/ibm_acpi.c
===================================================================
--- 2.6.18.orig/drivers/acpi/ibm_acpi.c
+++ 2.6.18/drivers/acpi/ibm_acpi.c
@@ -317,7 +317,8 @@ enum fan_control_access_mode {
 enum fan_control_commands {
 	IBMACPI_FAN_CMD_SPEED 	= 0x0001,	/* speed command */
 	IBMACPI_FAN_CMD_LEVEL 	= 0x0002,	/* level command  */
-	IBMACPI_FAN_CMD_ENABLE	= 0x0004,	/* enable/disable cmd */
+	IBMACPI_FAN_CMD_ENABLE	= 0x0004,	/* enable/disable cmd,
+						 * and also watchdog cmd */
 };
 
 enum {					/* Fan control constants */
@@ -1718,6 +1719,7 @@ static enum fan_status_access_mode fan_s
 static enum fan_control_access_mode fan_control_access_mode;
 static enum fan_control_commands fan_control_commands;
 static int fan_control_status_known;
+static int fan_watchdog_maxinterval;
 
 static int fan_init(void)
 {
@@ -1727,6 +1729,7 @@ static int fan_init(void)
 	fan_control_access_mode = IBMACPI_FAN_WR_NONE;
 	fan_control_commands = 0;
 	fan_control_status_known = 1;
+	fan_watchdog_maxinterval = 0;
 
 	if (gfan_handle) {
 		/* 570, 600e/x, 770e, 770x */
@@ -1768,7 +1771,7 @@ static int fan_init(void)
 			} else {
 				fan_control_access_mode = IBMACPI_FAN_WR_TPEC;
 				fan_control_commands |= IBMACPI_FAN_CMD_LEVEL
-						 	| IBMACPI_FAN_CMD_ENABLE;
+							| IBMACPI_FAN_CMD_ENABLE;
 			}
 		}
 	}
@@ -1776,6 +1779,10 @@ static int fan_init(void)
 	return 0;
 }
 
+static void fan_watchdog_reset( void )
+{
+}
+
 static int fan_read(char *p)
 {
 	int len = 0;
@@ -1855,7 +1862,9 @@ static int fan_read(char *p)
 	}
 
 	if (fan_control_commands & IBMACPI_FAN_CMD_ENABLE)
-		len += sprintf(p + len, "commands:\tenable, disable\n");
+		len += sprintf(p + len, "commands:\tenable, disable, "
+				"watchdog <timeout>, (<timeout> is 0 (off), "
+				"1-120 (seconds))\n");
 
 	if (fan_control_commands & IBMACPI_FAN_CMD_SPEED)
 		len += sprintf(p + len, "commands:\tspeed <speed>"
@@ -1908,6 +1917,8 @@ static int fan_write_cmd_level(const cha
 			"access mode %d", fan_control_access_mode);
 		*rc = -EINVAL;
 	}
+
+	if (! *rc) fan_watchdog_reset();
 	return 1;
 }
 
@@ -1936,6 +1947,8 @@ static int fan_write_cmd_enable(const ch
 			"access mode %d", fan_control_access_mode);
 		*rc = -EINVAL;
 	}
+
+	if (! *rc) fan_watchdog_reset();
 	return 1;
 }
 
@@ -1963,6 +1976,8 @@ static int fan_write_cmd_disable(const c
 			"access mode %d", fan_control_access_mode);
 		*rc = -EINVAL;
 	}
+
+	if (! *rc) fan_watchdog_reset();
 	return 1;
 }
 
@@ -1991,6 +2006,24 @@ static int fan_write_cmd_speed(const cha
 			"access mode %d", fan_control_access_mode);
 		*rc = -EINVAL;
 	}
+
+	if (! *rc) fan_watchdog_reset();
+	return 1;
+}
+
+static int fan_write_cmd_watchdog(const char *cmd, int *rc)
+{
+	int interval;
+
+	if (sscanf(cmd, "watchdog %d", &interval) != 1)
+		return 0;
+
+	if (interval < 0 || interval > 120)
+		*rc = -EINVAL;
+	else
+		fan_watchdog_maxinterval = interval;
+
+	if (! *rc) fan_watchdog_reset();
 	return 1;
 }
 
@@ -2003,11 +2036,10 @@ static int fan_write(char *buf)
 		if ((fan_control_commands & IBMACPI_FAN_CMD_LEVEL) &&
 				fan_write_cmd_level(cmd, &rc))
 		    	continue;
-		else if ((fan_control_commands & IBMACPI_FAN_CMD_ENABLE) &&
-				fan_write_cmd_enable(cmd, &rc))
-		    	continue;
-		else if ((fan_control_commands & IBMACPI_FAN_CMD_ENABLE) &&
-				fan_write_cmd_disable(cmd, &rc))
+		else if ((fan_control_commands & IBMACPI_FAN_CMD_ENABLE) && (
+				fan_write_cmd_enable(cmd, &rc) ||
+				fan_write_cmd_disable(cmd, &rc) ||
+				fan_write_cmd_watchdog(cmd, &rc) ))
 		    	continue;
 		else if ((fan_control_commands & IBMACPI_FAN_CMD_SPEED) &&
 				fan_write_cmd_speed(cmd, &rc))

--
  "One disk to rule them all, One disk to find them. One disk to bring
  them all and in the darkness grind them. In the Land of Redmond
  where the shadows lie." -- The Silicon Valley Tarot
  Henrique Holschuh