[ltp] [patch 08/11] ibm-acpi: extend fan status functions

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


This patch fixes fan_read to return correct values for all fan access modes,
taking into account firmware bugs.  It also implements some fan access mode
status output that was missing.

Userspace ABI changes:
	1. Return status: enable/disable for *all* modes
	2. Return level: auto and level: disengaged for EC 0x2f access mode
	3. Return level: <number> for EC 0x2f access mode
	4. Return speed: unknwon in disengaged mode
	5. Return level 0 as well as "disabled" in level-aware access modes

Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
---
 drivers/acpi/ibm_acpi.c |   40 ++++++++++++++++++++++++++++++----------
 1 file changed, 30 insertions(+), 10 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
@@ -324,6 +324,11 @@ enum {					/* Fan control constants */
 	fan_status_offset = 0x2f,	/* EC register 0x2f */
 	fan_rpm_offset = 0x84,		/* EC register 0x84: LSB, 0x85 MSB (RPM)
 					 * 0x84 must be read before 0x85 */
+
+	IBMACPI_FAN_EC_DISENGAGED 	= 0x40,	/* EC mode: tachometer
+						 * disengaged */
+	IBMACPI_FAN_EC_AUTO		= 0x80, /* EC mode: auto fan
+						 * control */
 };
 
 static int ibm_thinkpad_ec_found;
@@ -1774,24 +1779,39 @@ static int fan_read(char *p)
 		if (unlikely(!acpi_evalf(gfan_handle, &status, NULL, "d")))
 			return -EIO;
 
-		len += sprintf(p + len, "level:\t\t%d\n", status);
-
+		len += sprintf(p + len, "status:\t\t%s\n"
+				"level:\t\t%d\n",
+				(status != 0) ? "enabled" : "disabled",
+				status );
 		break;
 
 	case IBMACPI_FAN_RD_TPEC:
 		/* all except 570, 600e/x, 770e, 770x */
 		if (unlikely(!acpi_ec_read(fan_status_offset, &status)))
 			return -EIO;
-		else
-			len += sprintf(p + len, "status:\t\t%s\n",
-				       enabled(status, 7));
 
-		if (unlikely(!acpi_ec_read(fan_rpm_offset, &lo) ||
-		    !acpi_ec_read(fan_rpm_offset + 1, &hi)))
-			return -EIO;
+		len += sprintf(p + len, "status:\t\t%s\n"
+				"level:\t\t",
+				(status != 0) ? "enabled" : "disabled" );
+		if (status & IBMACPI_FAN_EC_DISENGAGED)
+			/* Disengaged mode takes precedence */
+			len += sprintf(p + len, "disengaged\n");
+		else if (status & IBMACPI_FAN_EC_AUTO)
+			len += sprintf(p + len, "auto\n");
 		else
-			len += sprintf(p + len, "speed:\t\t%d\n",
-				       (hi << 8) + lo);
+			len += sprintf(p + len, "%d\n", status);
+
+		if (status & IBMACPI_FAN_EC_DISENGAGED)
+			/* tachometer is offline */
+			len += sprintf(p + len, "speed:\t\tunknown\n");
+		else {
+			if (unlikely(!acpi_ec_read(fan_rpm_offset, &lo) ||
+			          !acpi_ec_read(fan_rpm_offset + 1, &hi)))
+				return -EIO;
+			else
+				len += sprintf(p + len, "speed:\t\t%d\n",
+							(hi << 8) + lo);
+		}
 
 		break;
 

--
  "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