[ltp] [PATCH] New ibm-acpi patches for extended thermal sensor functionality

Henrique de Moraes Holschuh linux-thinkpad@linux-thinkpad.org
Sat, 16 Sep 2006 13:50:09 -0300


--OZkY3AIuv2LYvjdk
Content-Type: multipart/mixed; boundary="/unnNtmY43mpUSKx"
Content-Disposition: inline


--/unnNtmY43mpUSKx
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

Please test the attached patches.  They apply fine to 2.6.17 ibm-acpi, as
well as 2.6.18-rc ibm-acpi.

Your kernel may already have the dmi patch if you are using the -mm tree, or
if you are using tp-smapi.  Try applying it with "patch --dry-run" first.

If all works well, I will submit the patch upstream, for inclusion in the
-mm kernel, and maybe they will make it for 2.6.20.

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

--/unnNtmY43mpUSKx
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="dmi-decode-and-save-oem-string-information.patch"
Content-Transfer-Encoding: quoted-printable

This teaches dmi_decode() how to decode and save OEM Strings (type 11) DMI
information, which is currently discarded silently.  Existing code using
DMI is not affected.  Follows the "System Management BIOS (SMBIOS)
Specification" (http://www.dmtf.org/standards/smbios), and also the
userspace dmidecode.c code.

OEM Strings are the only safe way to identify some hardware, e.g., the
ThinkPad embedded controller used by the soon-to-be-submitted tp_smapi
driver.  This will also let us eliminate the long whitelist in the mainline
hdaps driver (in a future patch).

Signed-off-by: Shem Multinymous <multinymous@gmail.com>
Cc: Bjorn Helgaas <bjorn.helgaas@hp.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 drivers/firmware/dmi_scan.c |   23 +++++++++++++++++++++++
 include/linux/dmi.h         |    3 ++-
 2 files changed, 25 insertions(+), 1 deletion(-)

diff -puN drivers/firmware/dmi_scan.c~dmi-decode-and-save-oem-string-inform=
ation drivers/firmware/dmi_scan.c
--- a/drivers/firmware/dmi_scan.c~dmi-decode-and-save-oem-string-information
+++ a/drivers/firmware/dmi_scan.c
@@ -123,6 +123,26 @@ static void __init dmi_save_devices(stru
 		dev->type =3D *d++ & 0x7f;
 		dev->name =3D dmi_string(dm, *d);
 		dev->device_data =3D NULL;
+		list_add(&dev->list, &dmi_devices);
+	}
+}
+
+static void __init dmi_save_oem_strings_devices(struct dmi_header *dm)
+{
+	int i, count =3D *(u8 *)(dm + 1);
+	struct dmi_device *dev;
+
+	for (i =3D 1; i <=3D count; i++) {
+		dev =3D dmi_alloc(sizeof(*dev));
+		if (!dev) {
+			printk(KERN_ERR
+			   "dmi_save_oem_strings_devices: out of memory.\n");
+			break;
+		}
+
+		dev->type =3D DMI_DEV_TYPE_OEM_STRING;
+		dev->name =3D dmi_string(dm, i);
+		dev->device_data =3D NULL;
=20
 		list_add(&dev->list, &dmi_devices);
 	}
@@ -181,6 +201,9 @@ static void __init dmi_decode(struct dmi
 	case 10:	/* Onboard Devices Information */
 		dmi_save_devices(dm);
 		break;
+	case 11:	/* OEM Strings */
+		dmi_save_oem_strings_devices(dm);
+		break;
 	case 38:	/* IPMI Device Information */
 		dmi_save_ipmi_device(dm);
 	}
diff -puN include/linux/dmi.h~dmi-decode-and-save-oem-string-information in=
clude/linux/dmi.h
--- a/include/linux/dmi.h~dmi-decode-and-save-oem-string-information
+++ a/include/linux/dmi.h
@@ -27,7 +27,8 @@ enum dmi_device_type {
 	DMI_DEV_TYPE_ETHERNET,
 	DMI_DEV_TYPE_TOKENRING,
 	DMI_DEV_TYPE_SOUND,
-	DMI_DEV_TYPE_IPMI =3D -1
+	DMI_DEV_TYPE_IPMI =3D -1,
+	DMI_DEV_TYPE_OEM_STRING =3D -2
 };
=20
 struct dmi_header {
_

--/unnNtmY43mpUSKx
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="ibm-acpi-extended-thermal-sensors.patch"
Content-Transfer-Encoding: quoted-printable

This patch extends ibm-acpi thermal sensor support for the extra eight
sensors available on newer ThinkPad models, that can be accessed only
through EC register reads using the ACPI EC direct register access.

It detects a new-style ThinkPad Embedded Controller (those supporting
field-upgradeable firmware), using a single DMI match (requires an extra
patch from the -mm tree, dmi-decode-and-save-oem-string-information.patch).
ThinkPads with new-style firmware appear to have a sane, forwards-
compatible register map (confirmed by direct verification of ecdumps from
various users for various ThinkPad models), where unused registers always
return zero.  This is used to auto-detect firmware support for the eight
extra sensors.

Support for older ThinkPad models is unchanged.  Support for ThinkPads with
only 8 thermal sensors but with a new-style EC is migrated from the old
ThinkPad-specific TMPx ACPI methods, to the new (also ThinkPad-specific)=20
direct EC register map access mode, for simplicity.

This patch also updates ibm-acpi.txt for the new functionality.

Information for this patch was gathered by the community in the linux-
thinkpad mailinglist, ThinkWiki, and thinkpads.com forums, by observing=20
the ecdump output in various thinkpad models.  The DMI match was tracked
down using the table at http://thinkwiki.org/wiki/List_of_DMI_IDs

Signed-off-by: Henrique de Moraes Holschuh <hmh@debian.org>

 Documentation/ibm-acpi.txt |   43 ++++++++++++++++------
 drivers/acpi/ibm_acpi.c    |   85 ++++++++++++++++++++++++++++++++++++----=
-----
 2 files changed, 100 insertions(+), 28 deletions(-)


--- a/drivers/acpi/ibm_acpi.c	2006-09-03 15:25:44.000000000 -0300
+++ b/drivers/acpi/ibm_acpi.c	2006-09-03 15:10:26.000000000 -0300
@@ -79,6 +79,7 @@
 #include <linux/types.h>
 #include <linux/proc_fs.h>
 #include <asm/uaccess.h>
+#include <linux/dmi.h>
=20
 #include <acpi/acpi_drivers.h>
 #include <acpi/acnamesp.h>
@@ -216,6 +217,14 @@
 #define IBM_HKEY_HID	"IBM0068"
 #define IBM_PCI_HID	"PNP0A03"
=20
+enum thermal_support_mode {
+	IBMACPI_THERMAL_NONE =3D 0,	/* No thermal support */
+	IBMACPI_THERMAL_ACPI_TMP07,	/* Use ACPI functions (older ECs) */
+	IBMACPI_THERMAL_TPEC,		/* Use EC registers through ACPI EC access */
+};
+
+static int ibm_thinkpad_ec_found;
+
 struct ibm_struct {
 	char *name;
 	char param[32];
@@ -1209,16 +1218,25 @@
 	return 1;
 }
=20
-static int thermal_tmp_supported;
+static enum thermal_support_mode thermal_tmp_supported;
 static int thermal_updt_supported;
=20
 static int thermal_init(void)
 {
-	/* temperatures not supported on 570, G4x, R30, R31, R32 */
-	thermal_tmp_supported =3D acpi_evalf(ec_handle, NULL, "TMP7", "qv");
+	if (ibm_thinkpad_ec_found) {
+		/* Direct EC access mode: faster and max
+		 * 16 sensors in newer models */
+		thermal_tmp_supported =3D IBMACPI_THERMAL_TPEC;
+	} else if (acpi_evalf(ec_handle, NULL, "TMP7", "qv")) {
+		/* Standard ACPI TMPx access, max 8 sensors */
+		thermal_tmp_supported =3D IBMACPI_THERMAL_ACPI_TMP07;
=20
-	/* 600e/x, 770e, 770x */
-	thermal_updt_supported =3D acpi_evalf(ec_handle, NULL, "UPDT", "qv");
+		/* 600e/x, 770e, 770x */
+		thermal_updt_supported =3D acpi_evalf(ec_handle, NULL, "UPDT", "qv");
+	} else {
+		/* temperatures not supported on 570, G4x, R30, R31, R32 */
+		thermal_tmp_supported =3D IBMACPI_THERMAL_NONE;
+	}
=20
 	return 0;
 }
@@ -1226,14 +1244,27 @@
 static int thermal_read(char *p)
 {
 	int len =3D 0;
+	int i, t, n;
+	s8 tmp[16];
+	char tmpi[] =3D "TMPi";
+
+	len +=3D sprintf(p + len,	"temperatures:\t");
+
+	switch(thermal_tmp_supported) {
+	case IBMACPI_THERMAL_TPEC:
+		/* EC thermal registers: 0x78-7F, 0xC0-C7 */
+		t =3D 0;
+		for (i =3D 0; i < 8; i++) {
+			if (!acpi_ec_read(0x78 + i, &tmp[i]))
+				return -EIO;
+			if (!acpi_ec_read(0xC0 + i, &tmp[i+8]))
+				return -EIO;
+			t |=3D tmp[i+8];
+		}
+		n =3D (t !=3D 0) ? 16 : 8;
+		break;
=20
-	if (!thermal_tmp_supported)
-		len +=3D sprintf(p + len, "temperatures:\tnot supported\n");
-	else {
-		int i, t;
-		char tmpi[] =3D "TMPi";
-		s8 tmp[8];
-
+	case IBMACPI_THERMAL_ACPI_TMP07:
 		if (thermal_updt_supported)
 			if (!acpi_evalf(ec_handle, NULL, "UPDT", "v"))
 				return -EIO;
@@ -1247,12 +1278,21 @@
 			else
 				tmp[i] =3D t;
 		}
+		n =3D 8;
+		break;
=20
-		len +=3D sprintf(p + len,
-			       "temperatures:\t%d %d %d %d %d %d %d %d\n",
-			       tmp[0], tmp[1], tmp[2], tmp[3],
-			       tmp[4], tmp[5], tmp[6], tmp[7]);
+	case IBMACPI_THERMAL_NONE:
+	default:
+		len +=3D sprintf(p + len, "not supported");
+		n =3D 0;
+	}
+
+	i =3D 0;
+	while (n > 0) {
+		len +=3D sprintf(p + len, "%d ", tmp[i++]);
+		n--;
 	}
+	len +=3D sprintf(p + len, "\n");
=20
 	return len;
 }
@@ -1905,6 +1973,16 @@
 	remove_proc_entry(IBM_DIR, acpi_root_dir);
 }
=20
+static int __init check_dmi_for_ec(void)
+{
+	struct dmi_device *dev =3D NULL;
+	while ((dev =3D dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, dev))) {
+		if (strstr(dev->name, "IBM ThinkPad Embedded Controller"))
+			return 1;
+	}
+	return 0;
+}
+
 static int __init acpi_ibm_init(void)
 {
 	int ret, i;
@@ -1924,6 +2002,9 @@
 		return -ENODEV;
 	}
=20
+	/* Models with newer firmware report the EC in DMI */
+	ibm_thinkpad_ec_found =3D check_dmi_for_ec();
+
 	/* these handles are not required */
 	IBM_HANDLE_INIT(vid);
 	IBM_HANDLE_INIT(vid2);
--- a/Documentation/ibm-acpi.txt	2006-09-16 10:53:37.000000000 -0300
+++ b/Documentation/ibm-acpi.txt	2006-09-16 11:22:13.000000000 -0300
@@ -430,25 +430,44 @@
=20
 Most ThinkPads include six or more separate temperature sensors but
 only expose the CPU temperature through the standard ACPI methods.
-This feature shows readings from up to eight different sensors. Some
-readings may not be valid, e.g. may show large negative values. For
-example, on the X40, a typical output may be:
+This feature shows readings from up to eight different sensors on older
+ThinkPads, and up to sixteen different sensors on newer ThinkPads.=20
+Readings from sensors that are not available return -128.=20
=20
+No commands can be written to this file.
+
+For example, on the X40, a typical output may be:
 temperatures:   42 42 45 41 36 -128 33 -128
=20
-Thomas Gruber took his R51 apart and traced all six active sensors in
-his laptop (the location of sensors may vary on other models):
+On the T43/p, a typical output may be:
+temperatures:   48 48 36 52 38 -128 31 -128 48 52 48 -128 -128 -128 -128 -=
128=20
+
+The mapping of thermal sensors to physical locations varies depending on
+system-board model (and thus, on ThinkPad model).
+
+http://thinkwiki.org/wiki/Thermal_Sensors is a public wiki page that
+tries to track down these locations for various models.
+
+Most (newer?) models seem to follow this pattern:
=20
 1:  CPU
-2:  Mini PCI Module
-3:  HDD
 4:  GPU
-5:  Battery
-6:  N/A
-7:  Battery
-8:  N/A
+5:  Main battery: main sensor
+6:  Bay battery: main sensor
+7:  Main battery: secondary sensor
+8:  Bay battery: secondary sensor
+
+For the R51 (source: Thomas Gruber):
+2:  Mini-PCI
+3:  Internal HDD
+
+For the T43, T43/p (source: Shmidoax/Thinkwiki.org)
+2:  System board, left side (near PCMCIA slot), reported as HDAPS temp
+3:  PCMCIA slot
+9:  MCH (northbridge) to DRAM Bus
+10: ICH (southbridge), under Mini-PCI card, under touchpad
+11: Power regulator, underside of system board, below F2 key
=20
-No commands can be written to this file.
=20
 EXPERIMENTAL: Embedded controller reigster dump -- /proc/acpi/ibm/ecdump
 ------------------------------------------------------------------------

--/unnNtmY43mpUSKx--

--OZkY3AIuv2LYvjdk
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: Digital signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (GNU/Linux)

iQEVAwUBRQwrQYjztdzjjnrPAQKU3wgAkWcVbkLMTNLdxXqVT5hKxNR2eE6f7Bvt
IvIm+GQEaIIMph8girUffx2j6IDmNrL0SyhPIGoA3+nbv09qp7rgY628fAPYDWQc
GMSpMaKtpPIKcEDWcgg/c87qyXN6cdzhCo+/mKoKxo8X+1ueeiqAWf6Thm775nBB
/ASdQxQXHa1XOeR54zYOmNCgwTxwUKxTM2NyK+oRKWZ13aRL3IEwsro/i4sVA5EJ
ylfnF9FcS7K+WU8FinWjONZ4gnQWXy2App0aEMlcIHLhv6EIRdRo7GLcZjUNzaSg
X2/2yD7iIC7ZVx/GYybwf8Aj3GO9XoFUKmh1K84e0c84Q5iFcKpFTA==
=0Ehi
-----END PGP SIGNATURE-----

--OZkY3AIuv2LYvjdk--