You can subscribe to this list here.
2006 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(74) |
Dec
(26) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2007 |
Jan
(14) |
Feb
(70) |
Mar
(116) |
Apr
(64) |
May
(118) |
Jun
(39) |
Jul
(243) |
Aug
(68) |
Sep
(77) |
Oct
(136) |
Nov
(48) |
Dec
(38) |
2008 |
Jan
(100) |
Feb
(84) |
Mar
(21) |
Apr
(56) |
May
(24) |
Jun
(19) |
Jul
(47) |
Aug
(27) |
Sep
(20) |
Oct
(65) |
Nov
(54) |
Dec
(14) |
2009 |
Jan
(45) |
Feb
(12) |
Mar
(15) |
Apr
(42) |
May
(21) |
Jun
(41) |
Jul
(15) |
Aug
(25) |
Sep
(49) |
Oct
(20) |
Nov
(61) |
Dec
(139) |
2010 |
Jan
(42) |
Feb
(56) |
Mar
(30) |
Apr
(27) |
May
(40) |
Jun
(16) |
Jul
(28) |
Aug
(14) |
Sep
(16) |
Oct
(11) |
Nov
(9) |
Dec
(10) |
2011 |
Jan
(51) |
Feb
(15) |
Mar
(29) |
Apr
(17) |
May
(70) |
Jun
(37) |
Jul
(6) |
Aug
(20) |
Sep
(7) |
Oct
(18) |
Nov
(28) |
Dec
(9) |
2012 |
Jan
(11) |
Feb
(12) |
Mar
(25) |
Apr
(8) |
May
(11) |
Jun
(27) |
Jul
(25) |
Aug
(22) |
Sep
(7) |
Oct
(6) |
Nov
(8) |
Dec
(29) |
2013 |
Jan
(11) |
Feb
(16) |
Mar
(41) |
Apr
(5) |
May
(4) |
Jun
(27) |
Jul
(10) |
Aug
(21) |
Sep
(13) |
Oct
(16) |
Nov
(31) |
Dec
(13) |
2014 |
Jan
(2) |
Feb
(37) |
Mar
(39) |
Apr
(62) |
May
(13) |
Jun
(6) |
Jul
(3) |
Aug
(4) |
Sep
(15) |
Oct
(13) |
Nov
(45) |
Dec
(2) |
2015 |
Jan
(7) |
Feb
(85) |
Mar
(66) |
Apr
(14) |
May
(24) |
Jun
(127) |
Jul
(7) |
Aug
(9) |
Sep
|
Oct
(11) |
Nov
(2) |
Dec
(12) |
2016 |
Jan
(71) |
Feb
(17) |
Mar
(8) |
Apr
(26) |
May
(8) |
Jun
(12) |
Jul
|
Aug
(2) |
Sep
(11) |
Oct
(25) |
Nov
(139) |
Dec
(7) |
2017 |
Jan
(12) |
Feb
(12) |
Mar
(4) |
Apr
(8) |
May
(37) |
Jun
(12) |
Jul
(5) |
Aug
(5) |
Sep
(18) |
Oct
(21) |
Nov
(10) |
Dec
(91) |
2018 |
Jan
(35) |
Feb
(31) |
Mar
(1) |
Apr
(33) |
May
(15) |
Jun
(50) |
Jul
(10) |
Aug
(14) |
Sep
(5) |
Oct
(8) |
Nov
(53) |
Dec
(9) |
2019 |
Jan
|
Feb
|
Mar
(7) |
Apr
(14) |
May
(14) |
Jun
(5) |
Jul
(5) |
Aug
|
Sep
(2) |
Oct
(2) |
Nov
|
Dec
(2) |
2020 |
Jan
(9) |
Feb
(8) |
Mar
|
Apr
(11) |
May
(14) |
Jun
(35) |
Jul
(53) |
Aug
(23) |
Sep
(15) |
Oct
(6) |
Nov
(14) |
Dec
(8) |
2021 |
Jan
(9) |
Feb
(6) |
Mar
(14) |
Apr
(4) |
May
(3) |
Jun
(1) |
Jul
(7) |
Aug
(2) |
Sep
(10) |
Oct
(4) |
Nov
(26) |
Dec
(9) |
2022 |
Jan
(13) |
Feb
(1) |
Mar
(1) |
Apr
(7) |
May
(7) |
Jun
(17) |
Jul
(6) |
Aug
(9) |
Sep
|
Oct
(8) |
Nov
(6) |
Dec
|
2023 |
Jan
(1) |
Feb
|
Mar
|
Apr
(8) |
May
|
Jun
|
Jul
(4) |
Aug
(1) |
Sep
(13) |
Oct
(1) |
Nov
(9) |
Dec
(4) |
2024 |
Jan
(9) |
Feb
|
Mar
(5) |
Apr
(118) |
May
(4) |
Jun
(13) |
Jul
|
Aug
(4) |
Sep
(4) |
Oct
(16) |
Nov
(20) |
Dec
(3) |
2025 |
Jan
(7) |
Feb
(1) |
Mar
(3) |
Apr
(8) |
May
(15) |
Jun
(38) |
Jul
(2) |
Aug
(9) |
Sep
(2) |
Oct
|
Nov
|
Dec
|
From: Henrique de M. H. <hm...@hm...> - 2006-11-25 20:44:32
|
From: Henrique de Moraes Holschuh <hm...@hm...> This patch breaks fan_read mechanics into a generic function to get fan status and speed, and leaves only the procfs interface code in fan_read. Signed-off-by: Henrique de Moraes Holschuh <hm...@hm...> --- drivers/acpi/ibm_acpi.c | 78 ++++++++++++++++++++++++++++++++++++++++-= ------ 1 files changed, 66 insertions(+), 12 deletions(-) diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index ef8ac01..834485b 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -1738,36 +1738,90 @@ static int fan_init(void) return 0; } =20 -static int fan_read(char *p) +static int fan_get_status(u8 *status) { - int len =3D 0; - u8 lo, hi, status; + u8 s; =20 switch (fan_status_access_mode) { case IBMACPI_FAN_RD_ACPI_GFAN: /* 570, 600e/x, 770e, 770x */ - if (unlikely(!acpi_evalf(gfan_handle, &status, NULL, "d"))) + + if (unlikely(!acpi_evalf(gfan_handle, &s, NULL, "d"))) return -EIO; =20 - len +=3D sprintf(p + len, "level:\t\t%d\n", status); + if (likely(status)) + *status =3D s & 0x07; =20 break; =20 case IBMACPI_FAN_RD_TPEC: /* all except 570, 600e/x, 770e, 770x */ - if (unlikely(!acpi_ec_read(fan_status_offset, &status))) + if (unlikely(!acpi_ec_read(fan_status_offset, &s))) return -EIO; - else - len +=3D sprintf(p + len, "status:\t\t%s\n", - enabled(status, 7)); =20 + if (likely(status)) + *status =3D s; + + break; + + default: + return -ENXIO; + } + + return 0; +} + +static int fan_get_speed(unsigned int *speed) +{ + u8 hi, lo; + + switch (fan_status_access_mode) { + case IBMACPI_FAN_RD_TPEC: + /* all except 570, 600e/x, 770e, 770x */ if (unlikely(!acpi_ec_read(fan_rpm_offset, &lo) || !acpi_ec_read(fan_rpm_offset + 1, &hi))) return -EIO; - else - len +=3D sprintf(p + len, "speed:\t\t%d\n", - (hi << 8) + lo); =20 + if (likely(speed)) + *speed =3D (hi << 8) | lo; + + break; + + default: + return -ENXIO; + } + + return 0; +} + +static int fan_read(char *p) +{ + int len =3D 0; + int rc; + u8 status; + unsigned int speed =3D 0; + + switch (fan_status_access_mode) { + case IBMACPI_FAN_RD_ACPI_GFAN: + /* 570, 600e/x, 770e, 770x */ + if ((rc =3D fan_get_status(&status)) < 0) + return rc; + + len +=3D sprintf(p + len, "level:\t\t%d\n", status); + + break; + + case IBMACPI_FAN_RD_TPEC: + /* all except 570, 600e/x, 770e, 770x */ + if ((rc =3D fan_get_status(&status)) < 0) + return rc; + + len +=3D sprintf(p + len, "status:\t\t%s\n", enabled(status, 7)); + + if ((rc =3D fan_get_speed(&speed)) < 0) + return rc; + + len +=3D sprintf(p + len, "speed:\t\t%d\n", speed); break; =20 case IBMACPI_FAN_NONE: |
From: Henrique de M. H. <hm...@hm...> - 2006-11-25 20:44:12
|
From: Henrique de Moraes Holschuh <hm...@hm...> This patch cleans up fan_read so that it is much easier to read and extend. The patch fixes the userspace ABI to return "status: not supported" (like all other ibm-acpi functions) when neither fan status or fan control are possible. It also fixes the userspace ABI to return EIO if ACPI access to the EC fails, instead of returning "status: unreadable" or "speed: unreadable". Signed-off-by: Henrique de Moraes Holschuh <hm...@hm...> --- drivers/acpi/ibm_acpi.c | 40 ++++++++++++++++++++++++---------------- 1 files changed, 24 insertions(+), 16 deletions(-) diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index 4c836e2..ef8ac01 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -1741,40 +1741,48 @@ static int fan_init(void) static int fan_read(char *p) { int len =3D 0; - int s; u8 lo, hi, status; =20 - if (gfan_handle) { + switch (fan_status_access_mode) { + case IBMACPI_FAN_RD_ACPI_GFAN: /* 570, 600e/x, 770e, 770x */ - if (!acpi_evalf(gfan_handle, &s, NULL, "d")) + if (unlikely(!acpi_evalf(gfan_handle, &status, NULL, "d"))) return -EIO; =20 - len +=3D sprintf(p + len, "level:\t\t%d\n", s); - } else { + len +=3D sprintf(p + len, "level:\t\t%d\n", status); + + break; + + case IBMACPI_FAN_RD_TPEC: /* all except 570, 600e/x, 770e, 770x */ - if (!acpi_ec_read(fan_status_offset, &status)) - len +=3D sprintf(p + len, "status:\t\tunreadable\n"); + if (unlikely(!acpi_ec_read(fan_status_offset, &status))) + return -EIO; else len +=3D sprintf(p + len, "status:\t\t%s\n", enabled(status, 7)); =20 - if (!acpi_ec_read(fan_rpm_offset, &lo) || - !acpi_ec_read(fan_rpm_offset + 1, &hi)) - len +=3D sprintf(p + len, "speed:\t\tunreadable\n"); + if (unlikely(!acpi_ec_read(fan_rpm_offset, &lo) || + !acpi_ec_read(fan_rpm_offset + 1, &hi))) + return -EIO; else len +=3D sprintf(p + len, "speed:\t\t%d\n", (hi << 8) + lo); + + break; + + case IBMACPI_FAN_NONE: + default: + len +=3D sprintf(p + len, "status:\t\tnot supported\n"); } =20 - if (sfan_handle) - /* 570, 770x-JL */ + if (fan_control_commands & IBMACPI_FAN_CMD_LEVEL) len +=3D sprintf(p + len, "commands:\tlevel <level>" " (<level> is 0-7)\n"); - if (!gfan_handle) - /* all except 570, 600e/x, 770e, 770x */ + + if (fan_control_commands & IBMACPI_FAN_CMD_ENABLE) len +=3D sprintf(p + len, "commands:\tenable, disable\n"); - if (fans_handle) - /* X31, X40 */ + + if (fan_control_commands & IBMACPI_FAN_CMD_SPEED) len +=3D sprintf(p + len, "commands:\tspeed <speed>" " (<speed> is 0-65535)\n"); =20 |
From: Henrique de M. H. <hm...@hm...> - 2006-11-25 20:43:53
|
From: Henrique de Moraes Holschuh <hm...@hm...> This patch lays some groundwork for a fan_read and fan_write cleanup in t= he next patches. To do so, it provides a new fan_init initializer, and also= some constants (through enums). Signed-off-by: Henrique de Moraes Holschuh <hm...@hm...> --- drivers/acpi/ibm_acpi.c | 81 +++++++++++++++++++++++++++++++++++++++++= +++++- 1 files changed, 79 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index 491c413..4c836e2 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -231,6 +231,31 @@ struct ibm_thermal_sensors_struct { s32 temp[IBMACPI_MAX_THERMAL_SENSORS]; }; =20 +enum fan_status_access_mode { + IBMACPI_FAN_NONE =3D 0, /* No fan status or control */ + IBMACPI_FAN_RD_ACPI_GFAN, /* Use ACPI GFAN */ + IBMACPI_FAN_RD_TPEC, /* Use ACPI EC regs 0x2f, 0x84-0x85 */ +}; + +enum fan_control_access_mode { + IBMACPI_FAN_WR_NONE =3D 0, /* No fan control */ + IBMACPI_FAN_WR_ACPI_SFAN, /* Use ACPI SFAN */ + IBMACPI_FAN_WR_TPEC, /* Use ACPI EC reg 0x2f */ + IBMACPI_FAN_WR_ACPI_FANS, /* Use ACPI FANS and EC reg 0x2f */ +}; + +enum fan_control_commands { + IBMACPI_FAN_CMD_SPEED =3D 0x0001, /* speed command */ + IBMACPI_FAN_CMD_LEVEL =3D 0x0002, /* level command */ + IBMACPI_FAN_CMD_ENABLE =3D 0x0004, /* enable/disable cmd */ +}; + +enum { /* Fan control constants */ + fan_status_offset =3D 0x2f, /* EC register 0x2f */ + fan_rpm_offset =3D 0x84, /* EC register 0x84: LSB, 0x85 MSB (RPM) + * 0x84 must be read before 0x85 */ +}; + static int ibm_thinkpad_ec_found; =20 struct ibm_struct { @@ -1659,8 +1684,59 @@ static int volume_write(char *buf) return 0; } =20 -static int fan_status_offset =3D 0x2f; -static int fan_rpm_offset =3D 0x84; +static enum fan_status_access_mode fan_status_access_mode; +static enum fan_control_access_mode fan_control_access_mode; +static enum fan_control_commands fan_control_commands; + +static int fan_init(void) +{ + u8 status; + + fan_status_access_mode =3D IBMACPI_FAN_NONE; + fan_control_access_mode =3D IBMACPI_FAN_WR_NONE; + fan_control_commands =3D 0; + + if (gfan_handle) { + /* 570, 600e/x, 770e, 770x */ + fan_status_access_mode =3D IBMACPI_FAN_RD_ACPI_GFAN; + } else { + /* all other ThinkPads: note that even old-style + * ThinkPad ECs supports the fan control register */ + if (likely(acpi_ec_read(fan_status_offset, &status))) { + fan_status_access_mode =3D IBMACPI_FAN_RD_TPEC; + } else { + printk(IBM_ERR + "ThinkPad ACPI EC access misbehaving, " + "fan status and control unavailable\n"); + return 0; + } + } + + if (sfan_handle) { + /* 570, 770x-JL */ + fan_control_access_mode =3D IBMACPI_FAN_WR_ACPI_SFAN; + fan_control_commands |=3D IBMACPI_FAN_CMD_LEVEL; + } else { + if (!gfan_handle) { + /* gfan without sfan means no fan control */ + /* all other models implement TP EC 0x2f control */ + + if (fans_handle) { + /* X31, X40 */ + fan_control_access_mode =3D + IBMACPI_FAN_WR_ACPI_FANS; + fan_control_commands |=3D + IBMACPI_FAN_CMD_SPEED | + IBMACPI_FAN_CMD_ENABLE; + } else { + fan_control_access_mode =3D IBMACPI_FAN_WR_TPEC; + fan_control_commands |=3D IBMACPI_FAN_CMD_ENABLE; + } + } + } + + return 0; +} =20 static int fan_read(char *p) { @@ -1849,6 +1925,7 @@ static struct ibm_struct ibms[] =3D { .name =3D "fan", .read =3D fan_read, .write =3D fan_write, + .init =3D fan_init, .experimental =3D 1, }, }; |
From: Henrique de M. H. <hm...@hm...> - 2006-11-25 20:43:33
|
From: Henrique de Moraes Holschuh <hm...@hm...> The A31 has a very atypical layout, so I separated its thermal sensors location in a separate patch. Signed-off-by: Henrique de Moraes Holschuh <hm...@hm...> --- Documentation/ibm-acpi.txt | 11 +++++++++++ 1 files changed, 11 insertions(+), 0 deletions(-) diff --git a/Documentation/ibm-acpi.txt b/Documentation/ibm-acpi.txt index 30f09e7..333b8eb 100644 --- a/Documentation/ibm-acpi.txt +++ b/Documentation/ibm-acpi.txt @@ -448,6 +448,17 @@ http://thinkwiki.org/wiki/Thermal_Sensor 10: ICH (southbridge), under Mini-PCI card, under touchpad 11: Power regulator, underside of system board, below F2 key =20 +The A31 has a very atypical layout for the thermal sensors +(source: Milos Popovic, http://thinkwiki.org/wiki/Thermal_Sensors#ThinkP= ad_A31) +1: CPU +2: Main Battery: main sensor +3: Power Converter +4: Bay Battery: main sensor +5: MCH (northbridge) +6: PCMCIA/ambient +7: Main Battery: secondary sensor +8: Bay Battery: secondary sensor + =20 EXPERIMENTAL: Embedded controller register dump -- /proc/acpi/ibm/ecdump ------------------------------------------------------------------------ |
From: Henrique de M. H. <hm...@hm...> - 2006-11-25 20:43:18
|
From: Henrique de Moraes Holschuh <hm...@hm...> This patch extends ibm-acpi to support reading thermal sensors directly through ACPI EC register access. It uses a DMI match to detect ThinkPads with a new-style embedded controller, that are known to have forward- compatible register maps and use 0x00 to fill in non-used registers and export thermal sensors at EC offsets 0x78-7F and 0xC0-C7. Direct ACPI EC register access is implemented for 8-sensor and 16-sensor new-style ThinkPad controller firmwares as an experimental feature. The code does some limited sanity checks on the temperatures read through EC access, and will default to the old ACPI TMP0-7 mode if anything is amiss= . Userspace ABI is not changed for 8 sensors, but /proc/acpi/ibm/thermal is extended for 16 sensors if the firmware supports 16 sensors. A documentation update is also provided. The information about the ThinkPad register map was determined by studyin= g ibm-acpi "ecdump" output from various ThinkPad models, submitted by subscribers of the linux-thinkpad mailinglist. Futher information was gathered from the DSDT tables, as they describe the EC register map in recent ThinkPads. DSDT source shows that TMP0-7 access and direct register access are actually the same thing on these firmwares, but unfortunately IBM never did update their DSDT EC register map to export TMP8-TMP15 for the second range of sensors. Signed-off-by: Henrique de Moraes Holschuh <hm...@hm...> --- Documentation/ibm-acpi.txt | 55 ++++++++++++++++++++------ drivers/acpi/ibm_acpi.c | 93 ++++++++++++++++++++++++++++++++++++++= +++++- 2 files changed, 134 insertions(+), 14 deletions(-) diff --git a/Documentation/ibm-acpi.txt b/Documentation/ibm-acpi.txt index e50595b..30f09e7 100644 --- a/Documentation/ibm-acpi.txt +++ b/Documentation/ibm-acpi.txt @@ -398,25 +398,56 @@ Temperature sensors -- /proc/acpi/ibm/th =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 it has experimental support for up to sixteen different +sensors on newer ThinkPads. Readings from sensors that are not availabl= e +return -128. =20 +No commands can be written to this file. + +EXPERIMENTAL: The 16-sensors feature is marked EXPERIMENTAL because the +implementation directly accesses hardware registers and may not work as +expected. USE WITH CAUTION! To use this feature, you need to supply the +experimental=3D1 parameter when loading the module. When EXPERIMENTAL +mode is enabled, reading the first 8 sensors on newer ThinkPads will +also use an new experimental thermal sensor access mode. + +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): +EXPERIMENTAL: 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 + +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 +2: (depends on model) +3: (depends on model) 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 +9-15: (depends on model) + +For the R51 (source: Thomas Gruber): +2: Mini-PCI +3: Internal HDD + +For the T43, T43/p (source: Shmidoax/Thinkwiki.org) +http://thinkwiki.org/wiki/Thermal_Sensors#ThinkPad_T43.2C_T43p +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 register dump -- /proc/acpi/ibm/ecdump ------------------------------------------------------------------------ diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index 3a8f223..491c413 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -80,6 +80,7 @@ #include <linux/proc_fs.h> #include <linux/backlight.h> #include <asm/uaccess.h> +#include <linux/dmi.h> =20 #include <acpi/acpi_drivers.h> #include <acpi/acnamesp.h> @@ -221,13 +222,17 @@ enum thermal_access_mode { IBMACPI_THERMAL_NONE =3D 0, /* No thermal support */ IBMACPI_THERMAL_ACPI_TMP07, /* Use ACPI TMP0-7 */ IBMACPI_THERMAL_ACPI_UPDT, /* Use ACPI TMP0-7 with UPDT */ + IBMACPI_THERMAL_TPEC_8, /* Use ACPI EC regs, 8 sensors */ + IBMACPI_THERMAL_TPEC_16, /* Use ACPI EC regs, 16 sensors */ }; =20 -#define IBMACPI_MAX_THERMAL_SENSORS 8 /* Max thermal sensors supported *= / +#define IBMACPI_MAX_THERMAL_SENSORS 16 /* Max thermal sensors supported = */ struct ibm_thermal_sensors_struct { s32 temp[IBMACPI_MAX_THERMAL_SENSORS]; }; =20 +static int ibm_thinkpad_ec_found; + struct ibm_struct { char *name; char param[32]; @@ -1290,7 +1295,52 @@ static enum thermal_access_mode thermal_ =20 static int thermal_init(void) { - if (acpi_evalf(ec_handle, NULL, "TMP7", "qv")) { + u8 t, ta1, ta2; + int i; + int acpi_tmp7 =3D acpi_evalf(ec_handle, NULL, "TMP7", "qv"); + + if (ibm_thinkpad_ec_found && experimental) { + /* + * Direct EC access mode: sensors at registers + * 0x78-0x7F, 0xC0-0xC7. Registers return 0x00 for + * non-implemented, thermal sensors return 0x80 when + * not available + */ + + ta1 =3D ta2 =3D 0; + for (i =3D 0; i < 8; i++) { + if (likely(acpi_ec_read(0x78 + i, &t))) { + ta1 |=3D t; + } else { + ta1 =3D 0; + break; + } + if (likely(acpi_ec_read(0xC0 + i, &t))) { + ta2 |=3D t; + } else { + ta1 =3D 0; + break; + } + } + if (ta1 =3D=3D 0) { + /* This is sheer paranoia, but we handle it anyway */ + if (acpi_tmp7) { + printk(IBM_ERR + "ThinkPad ACPI EC access misbehaving, " + "falling back to ACPI TMPx access mode\n"); + thermal_read_mode =3D IBMACPI_THERMAL_ACPI_TMP07; + } else { + printk(IBM_ERR + "ThinkPad ACPI EC access misbehaving, " + "disabling thermal sensors access\n"); + thermal_read_mode =3D IBMACPI_THERMAL_NONE; + } + } else { + thermal_read_mode =3D + (ta2 !=3D 0) ? + IBMACPI_THERMAL_TPEC_16 : IBMACPI_THERMAL_TPEC_8; + } + } else if (acpi_tmp7) { if (acpi_evalf(ec_handle, NULL, "UPDT", "qv")) { /* 600e/x, 770e, 770x */ thermal_read_mode =3D IBMACPI_THERMAL_ACPI_UPDT; @@ -1309,12 +1359,30 @@ static int thermal_init(void) static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s) { int i, t; + s8 tmp; char tmpi[] =3D "TMPi"; =20 if (!s) return -EINVAL; =20 switch (thermal_read_mode) { +#if IBMACPI_MAX_THERMAL_SENSORS >=3D 16 + case IBMACPI_THERMAL_TPEC_16: + for (i =3D 0; i < 8; i++) { + if (!acpi_ec_read(0xC0 + i, &tmp)) + return -EIO; + s->temp[i + 8] =3D tmp * 1000; + } + /* fallthrough */ +#endif + case IBMACPI_THERMAL_TPEC_8: + for (i =3D 0; i < 8; i++) { + if (!acpi_ec_read(0x78 + i, &tmp)) + return -EIO; + s->temp[i] =3D tmp * 1000; + } + return (thermal_read_mode =3D=3D IBMACPI_THERMAL_TPEC_16) ? 16 : 8; + case IBMACPI_THERMAL_ACPI_UPDT: if (!acpi_evalf(ec_handle, NULL, "UPDT", "v")) return -EIO; @@ -2051,6 +2119,24 @@ static void acpi_ibm_exit(void) remove_proc_entry(IBM_DIR, acpi_root_dir); } =20 +static int __init check_dmi_for_ec(void) +{ + struct dmi_device *dev =3D NULL; + + /* + * ThinkPad T23 or newer, A31 or newer, R50e or newer, + * X32 or newer, all Z series; Some models must have an + * up-to-date BIOS or they will not be detected. + * + * See http://thinkwiki.org/wiki/List_of_DMI_IDs + */ + 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; @@ -2070,6 +2156,9 @@ static int __init acpi_ibm_init(void) 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); |
From: Henrique de M. H. <hm...@hm...> - 2006-11-25 20:42:53
|
From: Henrique de Moraes Holschuh <hm...@hm...> This patch consolidades all decisions regarding the strategy to be used t= o read thinkpad thermal sensors into a single enum, and refactors the thermal sensor reading code to use a much more readable (and easier to extend) switch() construct, in a separate function. Signed-off-by: Henrique de Moraes Holschuh <hm...@hm...> --- drivers/acpi/ibm_acpi.c | 90 ++++++++++++++++++++++++++++++++++-------= ------ 1 files changed, 65 insertions(+), 25 deletions(-) diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index 622626b..3a8f223 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -217,6 +217,17 @@ IBM_HANDLE(sfan, ec, "SFAN", /* 570 */ #define IBM_HKEY_HID "IBM0068" #define IBM_PCI_HID "PNP0A03" =20 +enum thermal_access_mode { + IBMACPI_THERMAL_NONE =3D 0, /* No thermal support */ + IBMACPI_THERMAL_ACPI_TMP07, /* Use ACPI TMP0-7 */ + IBMACPI_THERMAL_ACPI_UPDT, /* Use ACPI TMP0-7 with UPDT */ +}; + +#define IBMACPI_MAX_THERMAL_SENSORS 8 /* Max thermal sensors supported *= / +struct ibm_thermal_sensors_struct { + s32 temp[IBMACPI_MAX_THERMAL_SENSORS]; +}; + struct ibm_struct { char *name; char param[32]; @@ -1275,50 +1286,79 @@ static int acpi_ec_write(int i, u8 v) return 1; } =20 -static int thermal_tmp_supported; -static int thermal_updt_supported; +static enum thermal_access_mode thermal_read_mode; =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"); - - /* 600e/x, 770e, 770x */ - thermal_updt_supported =3D acpi_evalf(ec_handle, NULL, "UPDT", "qv"); + if (acpi_evalf(ec_handle, NULL, "TMP7", "qv")) { + if (acpi_evalf(ec_handle, NULL, "UPDT", "qv")) { + /* 600e/x, 770e, 770x */ + thermal_read_mode =3D IBMACPI_THERMAL_ACPI_UPDT; + } else { + /* Standard ACPI TMPx access, max 8 sensors */ + thermal_read_mode =3D IBMACPI_THERMAL_ACPI_TMP07; + } + } else { + /* temperatures not supported on 570, G4x, R30, R31, R32 */ + thermal_read_mode =3D IBMACPI_THERMAL_NONE; + } =20 return 0; } =20 -static int thermal_read(char *p) +static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s) { - int len =3D 0; + int i, t; + char tmpi[] =3D "TMPi"; =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]; + if (!s) + return -EINVAL; =20 - if (thermal_updt_supported) - if (!acpi_evalf(ec_handle, NULL, "UPDT", "v")) + switch (thermal_read_mode) { + case IBMACPI_THERMAL_ACPI_UPDT: + if (!acpi_evalf(ec_handle, NULL, "UPDT", "v")) + return -EIO; + for (i =3D 0; i < 8; i++) { + tmpi[3] =3D '0' + i; + if (!acpi_evalf(ec_handle, &t, tmpi, "d")) return -EIO; + s->temp[i] =3D (t - 2732) * 100; + } + return 8; =20 + case IBMACPI_THERMAL_ACPI_TMP07: for (i =3D 0; i < 8; i++) { tmpi[3] =3D '0' + i; if (!acpi_evalf(ec_handle, &t, tmpi, "d")) return -EIO; - if (thermal_updt_supported) - tmp[i] =3D (t - 2732 + 5) / 10; - else - tmp[i] =3D t; + s->temp[i] =3D t * 1000; } + return 8; =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: + return 0; } +} + +static int thermal_read(char *p) +{ + int len =3D 0; + int n, i; + struct ibm_thermal_sensors_struct t; + + n =3D thermal_get_sensors(&t); + if (unlikely(n < 0)) + return n; + + len +=3D sprintf(p + len, "temperatures:\t"); + + if (n > 0) { + for (i =3D 0; i < (n - 1); i++) + len +=3D sprintf(p + len, "%d ", t.temp[i] / 1000); + len +=3D sprintf(p + len, "%d\n", t.temp[i] / 1000); + } else + len +=3D sprintf(p + len, "not supported\n"); =20 return len; } |
From: Henrique de M. H. <hm...@hm...> - 2006-11-25 20:42:37
|
From: Henrique de Moraes Holschuh <hm...@hm...> This patch just makes drives/acpi/ibm-acpi.c Lindent-clean, as requested = by Len Brown. Signed-off-by: Henrique de Moraes Holschuh <hm...@hm...> --- drivers/acpi/ibm_acpi.c | 24 ++++++++++++------------ 1 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index 9baae34..622626b 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -584,8 +584,7 @@ static int wan_status(void) { int status; =20 - if (!wan_supported || - !acpi_evalf(hkey_handle, &status, "GWAN", "d")) + if (!wan_supported || !acpi_evalf(hkey_handle, &status, "GWAN", "d")) status =3D 0; =20 return status; @@ -910,6 +909,7 @@ static int _sta(acpi_handle handle) =20 return status; } + #ifdef CONFIG_ACPI_IBM_DOCK #define dock_docked() (_sta(dock_handle) & 1) =20 @@ -1386,12 +1386,12 @@ static int brightness_offset =3D 0x31; =20 static int brightness_get(struct backlight_device *bd) { - u8 level; - if (!acpi_ec_read(brightness_offset, &level)) - return -EIO; + u8 level; + if (!acpi_ec_read(brightness_offset, &level)) + return -EIO; =20 - level &=3D 0x7; - return level; + level &=3D 0x7; + return level; } =20 static int brightness_read(char *p) @@ -1992,10 +1992,10 @@ IBM_PARAM(volume); IBM_PARAM(fan); =20 static struct backlight_properties ibm_backlight_data =3D { - .owner =3D THIS_MODULE, - .get_brightness =3D brightness_get, - .update_status =3D brightness_update_status, - .max_brightness =3D 7, + .owner =3D THIS_MODULE, + .get_brightness =3D brightness_get, + .update_status =3D brightness_update_status, + .max_brightness =3D 7, }; =20 static void acpi_ibm_exit(void) @@ -2074,7 +2074,7 @@ static int __init acpi_ibm_init(void) =20 ibm_backlight_device =3D backlight_device_register("ibm", NULL, &ibm_backlight_data); - if (IS_ERR(ibm_backlight_device)) { + if (IS_ERR(ibm_backlight_device)) { printk(IBM_ERR "Could not register ibm backlight device\n"); ibm_backlight_device =3D NULL; acpi_ibm_exit(); |
From: Henrique de M. H. <hm...@hm...> - 2006-11-25 20:42:13
|
From: Henrique de Moraes Holschuh <hm...@hm...> ibm-acpi uses sub-device names like ibm/hotkey, which get in the way of a sysfs conversion. Fix it to use ibm_hotkey instead. Thanks to Zhang Rui for noticing this. Signed-off-by: Henrique de Moraes Holschuh <hm...@hm...> --- drivers/acpi/ibm_acpi.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index 9658253..9baae34 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -1854,7 +1854,7 @@ static int __init register_driver(struct } =20 memset(ibm->driver, 0, sizeof(struct acpi_driver)); - sprintf(ibm->driver->name, "%s/%s", IBM_NAME, ibm->name); + sprintf(ibm->driver->name, "%s_%s", IBM_NAME, ibm->name); ibm->driver->ids =3D ibm->hid; ibm->driver->ops.add =3D &ibm_device_add; =20 |
From: Henrique de M. H. <hm...@hm...> - 2006-11-25 20:41:57
|
This patch series contains the ibm-acpi devel queue for 2006-11-25. Please merge for acpi-test. Patch 1 fixes sub-driver naming so that it doesn't get in the way of a ACPI sysfs conversion work. Patch 2 just does some Lindent housekeeping work, as Len said he likes code to be as Lindent-clean as possible. Patches 3-5 extend thermal support for the new thinkpads, and updates thermal docs. Patches 6-13 extend fan support for new thinkpads, so people will stop using ecdump to directly modify EC registers ;-) Patches 14-15 implement a work-around for a bug in the EC firmware in certain thinkpads, see http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Bug:_Fan_control_l= oop_status_is_not_initialized Patch 16 adds a watchdog functionality for fan control that has been requested by developers of userspace fan control utilities. Many thinkpads have very annoying out-of-the-box fan behaviour, so userspace fan control is quite widespread among T4x owners, for example. Patch 17 adds support for SATA ultrabay (advanced ultrabay), found in *60 and *61 x/t/z-series. Patch 18 makes ibm-acpi non-generic bay support optional. Patch 19 refactors backlight support so that it is in line with=20 the rest of the ibm-acpi driver code. Patches 20-21 are just housekeeping. This patch series is available for git pull from: git://repo.or.cz/linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git branch for-upstream/acpi-test. --=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 |
From: Henrique de M. H. <hm...@hm...> - 2006-11-25 17:47:57
|
On Sat, 25 Nov 2006, Evgeni Golov wrote: > On Sat, 25 Nov 2006 14:18:44 -0200 Henrique de Moraes Holschuh wrote: > > If you have upgraded your ThinkPad already to the *latest* BIOS, > > please send *by private mail* the output of dmidecode and also of > > "cat /proc/acpi/dsdt | gzip -f >dsdt.bin.gz". Please send the mails > > to ibm-acpi <at> hmh.eng.br. > > Done for my Z61m with latest (2.11) BIOS > > > Currently, these ThinkPads are *not* supported officialy in ibm-acpi, > > because I don't have the DSDTs, so your help would be much > > appreciated. > > But they seem to work correctly, didn't they? Not the bay, but still, I can't support what I can't even *try* to understand ;-) > I've allready added mine to the DMI ID List at ThinkWiki Thanks! -- "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 |
From: Evgeni G. <sar...@di...> - 2006-11-25 17:15:09
|
On Sat, 25 Nov 2006 14:18:44 -0200 Henrique de Moraes Holschuh wrote: > If you have upgraded your ThinkPad already to the *latest* BIOS, > please send *by private mail* the output of dmidecode and also of > "cat /proc/acpi/dsdt | gzip -f >dsdt.bin.gz". Please send the mails > to ibm-acpi <at> hmh.eng.br. Done for my Z61m with latest (2.11) BIOS > Currently, these ThinkPads are *not* supported officialy in ibm-acpi, > because I don't have the DSDTs, so your help would be much > appreciated. But they seem to work correctly, didn't they? > As usual, I will upload the DSDTs to acpi.sf.net, and fill in any > information that is missing in ThinkWiki, so that other driver > writers can also benefit from them. I've allready added mine to the DMI ID List at ThinkWiki regards Evgeni -- ^^^ | Evgeni -SargentD- Golov (sar...@di...) d(O_o)b | PGP-Key-ID: 0xAC15B50C >-|-< | WWW: http://www.die-welt.net ICQ: 54116744 / \ | IRC: #sod @ irc.german-freakz.net |
From: Henrique de M. H. <hm...@hm...> - 2006-11-25 16:18:52
|
Owners of the T60, Z60, Z61 (any submodel): If you have upgraded your ThinkPad already to the *latest* BIOS, please send *by private mail* the output of dmidecode and also of "cat /proc/acpi/dsdt | gzip -f >dsdt.bin.gz". Please send the mails to ibm-acpi <at> hmh.eng.br. Currently, these ThinkPads are *not* supported officialy in ibm-acpi, because I don't have the DSDTs, so your help would be much appreciated. As usual, I will upload the DSDTs to acpi.sf.net, and fill in any information that is missing in ThinkWiki, so that other driver writers can also benefit from them. -- "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 |
From: Zhang, R. <rui...@in...> - 2006-11-25 01:02:22
|
Yes, that's exactly what I want to change. :) Thanks. Best regards, Zhang.Rui(Ray) =20 -----Original Message----- From: Henrique de Moraes Holschuh [mailto:hm...@hm...]=20 Sent: 2006=C4=EA11=D4=C224=C8=D5 22:38 To: Zhang, Rui; Len Brown Cc: linux-acpi@vger; ibm...@li... Subject: [PATCH] ACPI: ibm-acpi: do not use / in driver names ACPI: ibm-acpi: do not use / in driver names ibm-acpi uses sub-device names like ibm/hotkey, which get in the way of a sysfs conversion. Fix it to use ibm_hotkey instead. Thanks to Zhang Rui for noticing this. Signed-off-by: Henrique de Moraes Holschuh <hm...@hm...> --- drivers/acpi/ibm_acpi.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index 9658253..9baae34 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -1854,7 +1854,7 @@ static int __init register_driver(struct } =20 memset(ibm->driver, 0, sizeof(struct acpi_driver)); - sprintf(ibm->driver->name, "%s/%s", IBM_NAME, ibm->name); + sprintf(ibm->driver->name, "%s_%s", IBM_NAME, ibm->name); ibm->driver->ids =3D ibm->hid; ibm->driver->ops.add =3D &ibm_device_add; =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 |
From: Thomas R. <tr...@su...> - 2006-11-24 15:07:49
|
On Wed, 2006-11-22 at 17:59 -0200, Henrique de Moraes Holschuh wrote: > From: Henrique de Moraes Holschuh <hm...@hm...> > > - if (!acpi_evalf(gfan_handle, &s, NULL, "d")) > + if (unlikely(!acpi_evalf(gfan_handle, &status, NULL, "d"))) > - if (!acpi_ec_read(fan_status_offset, &status)) > - len += sprintf(p + len, "status:\t\tunreadable\n"); > + if (unlikely(!acpi_ec_read(fan_status_offset, &status))) > + return -EIO; > - if (!acpi_ec_read(fan_rpm_offset, &lo) || > - !acpi_ec_read(fan_rpm_offset + 1, &hi)) > - len += sprintf(p + len, "speed:\t\tunreadable\n"); > + if (unlikely(!acpi_ec_read(fan_rpm_offset, &lo) || > + !acpi_ec_read(fan_rpm_offset + 1, &hi))) > + return -EIO; Hmm, just one little thing, which is probably not worth modifying. AFAIK likely/unlikely is only used at often processed optimized code. It might make sense here in general, but is normally not used for better reading and as it's just not worth it. I might be wrong and someone wants to correct me, it's just that other kernel parts don't show these often. Thomas |
From: Henrique de M. H. <hm...@hm...> - 2006-11-24 14:38:01
|
ACPI: ibm-acpi: do not use / in driver names ibm-acpi uses sub-device names like ibm/hotkey, which get in the way of a sysfs conversion. Fix it to use ibm_hotkey instead. Thanks to Zhang Rui for noticing this. Signed-off-by: Henrique de Moraes Holschuh <hm...@hm...> --- drivers/acpi/ibm_acpi.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index 9658253..9baae34 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -1854,7 +1854,7 @@ static int __init register_driver(struct } memset(ibm->driver, 0, sizeof(struct acpi_driver)); - sprintf(ibm->driver->name, "%s/%s", IBM_NAME, ibm->name); + sprintf(ibm->driver->name, "%s_%s", IBM_NAME, ibm->name); ibm->driver->ids = ibm->hid; ibm->driver->ops.add = &ibm_device_add; -- "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 |
From: Henrique de M. H. <hm...@hm...> - 2006-11-23 22:56:57
|
On Tue, 21 Nov 2006, Shem Multinymous wrote: > >This will cause a lot of cruft in repo.or.cz that I can't easily fix (I > >can't tell the git dumb push protocol to delete a remote branch. Heck, the > >thing is so dumb it can't even figure out it doesn't need to push > >something, > >unlike the pull protocol...). > > Really?! Yikes. > I would just ignore this and wait the feature is (inevitably) added. I have just found that a lot of the issues I had with git are to blame on cogito, including an extreme inneficiency on clone, and after purging cogito and switching to bare git and stgit, I am a much happier camper. Heck, the fact that git clone will clone *all* heads much faster than cogito can clone a single one when using --reference made me very happy indeed :p But I think I used pure git for the push, so the comment on it being a massive waster of bandwidth on initial pushes remains. -- "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 |
From: Henrique de M. H. <hm...@hm...> - 2006-11-22 20:14:44
|
From: Henrique de Moraes Holschuh <hm...@hm...> This patch implements a fan control safety watchdog, by request of the authors of userspace fan control scripts. 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 mak= e sure the fan is never left set to an unsafe level because of userspace problems. Users of the X31/X40/X41 "speed" command are on their own, the current implementation of "speed" is just too incomplete to be used safely, anyway. Better to never use it, and just use the "level" command instead= . The watchdog is programmed using echo "watchdog <number>" > fan, where number is the number of seconds to wait before doing an "enable", and zer= o disables the watchdog. Signed-off-by: Henrique de Moraes Holschuh <hm...@hm...> --- Documentation/ibm-acpi.txt | 20 +++++++++++++ drivers/acpi/ibm_acpi.c | 70 ++++++++++++++++++++++++++++++++++++++= ++++-- 2 files changed, 87 insertions(+), 3 deletions(-) diff --git a/Documentation/ibm-acpi.txt b/Documentation/ibm-acpi.txt index cbd3a60..0132d36 100644 --- a/Documentation/ibm-acpi.txt +++ b/Documentation/ibm-acpi.txt @@ -670,6 +670,26 @@ example: =20 modprobe ibm_acpi hotkey=3Denable,0xffff video=3Dauto_disable =20 +The ibm-acpi kernel driver can be programmed to revert the fan level +to a safe setting if userspace does not issue one of the fan commands: +"enable", "disable", "level" or "watchdog" within a configurable +ammount of time. To do this, use the "watchdog" command. + + echo 'watchdog <interval>' > /proc/acpi/ibm/fan + +Interval is the ammount of time in seconds to wait for one of the +above mentioned fan commands before reseting the fan level to a safe +one. If set to zero, the watchdog is disabled (default). When the +watchdog timer runs out, it does the exact equivalent of the "enable" +fan command. + +Note that the watchdog timer stops after it enables the fan. It will +be rearmed again automatically (using the same interval) when one of +the above mentioned fan commands is received. The fan watchdog is, +therefore, not suitable to protect against fan mode changes made +through means other than the "enable", "disable", and "level" fan +commands. + =20 Example Configuration --------------------- diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index c363349..2d49b12 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -82,6 +82,8 @@ #include <linux/backlight.h> #include <asm/uaccess.h> #include <linux/dmi.h> +#include <linux/jiffies.h> +#include <linux/workqueue.h> =20 #include <acpi/acpi_drivers.h> #include <acpi/acnamesp.h> @@ -348,7 +350,8 @@ enum fan_control_access_mode { enum fan_control_commands { IBMACPI_FAN_CMD_SPEED =3D 0x0001, /* speed command */ IBMACPI_FAN_CMD_LEVEL =3D 0x0002, /* level command */ - IBMACPI_FAN_CMD_ENABLE =3D 0x0004, /* enable/disable cmd */ + IBMACPI_FAN_CMD_ENABLE =3D 0x0004, /* enable/disable cmd, + * and also watchdog cmd */ }; =20 enum { /* Fan control constants */ @@ -1797,12 +1800,17 @@ static enum fan_control_commands fan_con static int fan_control_status_known; static u8 fan_control_initial_status; =20 +static void fan_watchdog_fire(void *ignored); +static int fan_watchdog_maxinterval; +static DECLARE_WORK(fan_watchdog_task, fan_watchdog_fire, NULL); + static int fan_init(void) { fan_status_access_mode =3D IBMACPI_FAN_NONE; fan_control_access_mode =3D IBMACPI_FAN_WR_NONE; fan_control_commands =3D 0; fan_control_status_known =3D 1; + fan_watchdog_maxinterval =3D 0; =20 if (gfan_handle) { /* 570, 600e/x, 770e, 770x */ @@ -1934,6 +1942,31 @@ static int fan_get_speed(unsigned int *s return 0; } =20 +static void fan_exit(void) +{ + cancel_delayed_work(&fan_watchdog_task); + flush_scheduled_work(); +} + +static void fan_watchdog_reset(void) +{ + static int fan_watchdog_active =3D 0; + + if (fan_watchdog_active) + cancel_delayed_work(&fan_watchdog_task); + + if (fan_watchdog_maxinterval > 0) { + fan_watchdog_active =3D 1; + if (!schedule_delayed_work(&fan_watchdog_task, + msecs_to_jiffies(fan_watchdog_maxinterval + * 1000))) { + printk(IBM_ERR "failed to schedule the fan watchdog, " + "watchdog will not trigger\n"); + } + } else + fan_watchdog_active =3D 0; +} + static int fan_read(char *p) { int len =3D 0; @@ -2007,7 +2040,9 @@ static int fan_read(char *p) } =20 if (fan_control_commands & IBMACPI_FAN_CMD_ENABLE) - len +=3D sprintf(p + len, "commands:\tenable, disable\n"); + len +=3D sprintf(p + len, "commands:\tenable, disable\n" + "commands:\twatchdog <timeout> (<timeout> is 0 (off), " + "1-120 (seconds))\n"); =20 if (fan_control_commands & IBMACPI_FAN_CMD_SPEED) len +=3D sprintf(p + len, "commands:\tspeed <speed>" @@ -2186,6 +2221,21 @@ static int fan_write_cmd_speed(const cha return 1; } =20 +static int fan_write_cmd_watchdog(const char *cmd, int *rc) +{ + int interval; + + if (sscanf(cmd, "watchdog %d", &interval) !=3D 1) + return 0; + + if (interval < 0 || interval > 120) + *rc =3D -EINVAL; + else + fan_watchdog_maxinterval =3D interval; + + return 1; +} + static int fan_write(char *buf) { char *cmd; @@ -2196,16 +2246,29 @@ static int fan_write(char *buf) fan_write_cmd_level(cmd, &rc)) && !((fan_control_commands & IBMACPI_FAN_CMD_ENABLE) && (fan_write_cmd_enable(cmd, &rc) || - fan_write_cmd_disable(cmd, &rc))) && + fan_write_cmd_disable(cmd, &rc) || + fan_write_cmd_watchdog(cmd, &rc))) && !((fan_control_commands & IBMACPI_FAN_CMD_SPEED) && fan_write_cmd_speed(cmd, &rc)) ) rc =3D -EINVAL; + else if (!rc) + fan_watchdog_reset(); } =20 return rc; } =20 +static void fan_watchdog_fire(void *ignored) +{ + printk(IBM_NOTICE "fan watchdog: enabling fan\n"); + if (fan_set_enable()) { + printk(IBM_ERR "fan watchdog: error while enabling fan\n"); + /* reschedule for later */ + fan_watchdog_reset(); + } +} + static struct ibm_struct ibms[] =3D { { .name =3D "driver", @@ -2317,6 +2380,7 @@ static struct ibm_struct ibms[] =3D { .read =3D fan_read, .write =3D fan_write, .init =3D fan_init, + .exit =3D fan_exit, .experimental =3D 1, }, }; |
From: Henrique de M. H. <hm...@hm...> - 2006-11-22 20:14:32
|
From: Henrique de Moraes Holschuh <hm...@hm...> The current code names the backlight device that controls the Thinkpad display brightness "ibm". This is not nearly descriptive enough. The ThinkPad can connect to more than one flat pannel display using the external VGA or DVI output, which we may be able to control over DCC someday. Also, Lenovo may introduce a ThinkPad with more than one internal LCD screen in the future. Or we could have LCD gadgets from ibm with backlights connected to the ThinkPad... This patch renames the main backlight device from "ibm" to "built-in_screen", which is far more descriptive and future-proof. Maybe the backlight devices refering to the built-in screen of laptops in other drivers should also be renamed to "built-in_screen" ? Signed-off-by: Henrique de Moraes Holschuh <hm...@hm...> Cc: Holger Macht <hm...@su...> Cc: Andy Whitcroft <ap...@sh...> Cc: Andrew Morton <ak...@os...> Cc: Len Brown <len...@in...> --- drivers/acpi/ibm_acpi.c | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index 96e945c..dab3fd1 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -1718,8 +1718,9 @@ static struct backlight_properties ibm_b =20 static int brightness_init(void) { - ibm_backlight_device =3D backlight_device_register("ibm", NULL, - &ibm_backlight_data); + ibm_backlight_device =3D backlight_device_register( + "built-in_screen", NULL, + &ibm_backlight_data); if (IS_ERR(ibm_backlight_device)) { printk(IBM_ERR "Could not register backlight device\n"); return PTR_ERR(ibm_backlight_device); |
From: Henrique de M. H. <hm...@hm...> - 2006-11-22 20:14:28
|
This patch series contains the ibm-acpi devel queue. Patch 1 just does some Lintend housekeeping work, as Len said he likes code to be as Lindent-clean as possible. Patches 2-4 extend thermal support for the new thinkpads, and updates thermal docs. Patches 5-12 extend fan support for new thinkpads, so people will stop using ecdump to directly modify EC registers ;-) Patches 13-14 implement a work-around for a bug in the EC firmware in certain thinkpads, see http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Bug:_Fan_control_l= oop_status_is_not_initialized Patch 15 adds a watchdog functionality for fan control that has been requested by developers of userspace fan control utilities. Many thinkpads have very annoying out-of-the-box fan behaviour, so userspace fan control is quite widespread among T4x owners, for example. Patch 16 adds support for the S30, thanks to help from Alex Deucher <ale...@gm...>. Patches 17-19 deals with backlight annoyances. I am all for sysfs support and using the generic classes, but the way it was added to ibm-acpi was not in line with the rest of the driver code. Patches 20-21 are just housekeeping. Please comment, I intend to push this upstream in two days, maybe even earlier than that. --=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 |
From: Henrique de M. H. <hm...@hm...> - 2006-11-22 20:14:10
|
From: Henrique de Moraes Holschuh <hm...@hm...> This patch just makes drives/acpi/ibm-acpi.c Lindent-clean, as requested = by Len Brown. Signed-off-by: Henrique de Moraes Holschuh <hm...@hm...> --- drivers/acpi/ibm_acpi.c | 24 ++++++++++++------------ 1 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index 9658253..a01bef7 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -584,8 +584,7 @@ static int wan_status(void) { int status; =20 - if (!wan_supported || - !acpi_evalf(hkey_handle, &status, "GWAN", "d")) + if (!wan_supported || !acpi_evalf(hkey_handle, &status, "GWAN", "d")) status =3D 0; =20 return status; @@ -910,6 +909,7 @@ static int _sta(acpi_handle handle) =20 return status; } + #ifdef CONFIG_ACPI_IBM_DOCK #define dock_docked() (_sta(dock_handle) & 1) =20 @@ -1386,12 +1386,12 @@ static int brightness_offset =3D 0x31; =20 static int brightness_get(struct backlight_device *bd) { - u8 level; - if (!acpi_ec_read(brightness_offset, &level)) - return -EIO; + u8 level; + if (!acpi_ec_read(brightness_offset, &level)) + return -EIO; =20 - level &=3D 0x7; - return level; + level &=3D 0x7; + return level; } =20 static int brightness_read(char *p) @@ -1992,10 +1992,10 @@ IBM_PARAM(volume); IBM_PARAM(fan); =20 static struct backlight_properties ibm_backlight_data =3D { - .owner =3D THIS_MODULE, - .get_brightness =3D brightness_get, - .update_status =3D brightness_update_status, - .max_brightness =3D 7, + .owner =3D THIS_MODULE, + .get_brightness =3D brightness_get, + .update_status =3D brightness_update_status, + .max_brightness =3D 7, }; =20 static void acpi_ibm_exit(void) @@ -2074,7 +2074,7 @@ static int __init acpi_ibm_init(void) =20 ibm_backlight_device =3D backlight_device_register("ibm", NULL, &ibm_backlight_data); - if (IS_ERR(ibm_backlight_device)) { + if (IS_ERR(ibm_backlight_device)) { printk(IBM_ERR "Could not register ibm backlight device\n"); ibm_backlight_device =3D NULL; acpi_ibm_exit(); |
From: Henrique de M. H. <hm...@hm...> - 2006-11-22 20:14:10
|
From: Henrique de Moraes Holschuh <hm...@hm...> This patch extends ibm-acpi to support reading thermal sensors directly through ACPI EC register access. It uses a DMI match to detect ThinkPads with a new-style embedded controller, that are known to have forward- compatible register maps and use 0x00 to fill in non-used registers and export thermal sensors at EC offsets 0x78-7F and 0xC0-C7. Direct ACPI EC register access is implemented for 8-sensor and 16-sensor new-style ThinkPad controller firmwares as an experimental feature. The code does some limited sanity checks on the temperatures read through EC access, and will default to the old ACPI TMP0-7 mode if anything is amiss= . Userspace ABI is not changed for 8 sensors, but /proc/acpi/ibm/thermal is extended for 16 sensors if the firmware supports 16 sensors. A documentation update is also provided. The information about the ThinkPad register map was determined by studyin= g ibm-acpi "ecdump" output from various ThinkPad models, submitted by subscribers of the linux-thinkpad mailinglist. Futher information was gathered from the DSDT tables, as they describe the EC register map in recent ThinkPads. DSDT source shows that TMP0-7 access and direct register access are actually the same thing on these firmwares, but unfortunately IBM never did update their DSDT EC register map to export TMP8-TMP15 for the second range of sensors. Signed-off-by: Henrique de Moraes Holschuh <hm...@hm...> --- Documentation/ibm-acpi.txt | 55 ++++++++++++++++++++------ drivers/acpi/ibm_acpi.c | 93 ++++++++++++++++++++++++++++++++++++++= +++++- 2 files changed, 134 insertions(+), 14 deletions(-) diff --git a/Documentation/ibm-acpi.txt b/Documentation/ibm-acpi.txt index e50595b..30f09e7 100644 --- a/Documentation/ibm-acpi.txt +++ b/Documentation/ibm-acpi.txt @@ -398,25 +398,56 @@ Temperature sensors -- /proc/acpi/ibm/th =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 it has experimental support for up to sixteen different +sensors on newer ThinkPads. Readings from sensors that are not availabl= e +return -128. =20 +No commands can be written to this file. + +EXPERIMENTAL: The 16-sensors feature is marked EXPERIMENTAL because the +implementation directly accesses hardware registers and may not work as +expected. USE WITH CAUTION! To use this feature, you need to supply the +experimental=3D1 parameter when loading the module. When EXPERIMENTAL +mode is enabled, reading the first 8 sensors on newer ThinkPads will +also use an new experimental thermal sensor access mode. + +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): +EXPERIMENTAL: 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 + +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 +2: (depends on model) +3: (depends on model) 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 +9-15: (depends on model) + +For the R51 (source: Thomas Gruber): +2: Mini-PCI +3: Internal HDD + +For the T43, T43/p (source: Shmidoax/Thinkwiki.org) +http://thinkwiki.org/wiki/Thermal_Sensors#ThinkPad_T43.2C_T43p +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 register dump -- /proc/acpi/ibm/ecdump ------------------------------------------------------------------------ diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index 067ff58..1f8a2c6 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -80,6 +80,7 @@ #include <linux/proc_fs.h> #include <linux/backlight.h> #include <asm/uaccess.h> +#include <linux/dmi.h> =20 #include <acpi/acpi_drivers.h> #include <acpi/acnamesp.h> @@ -221,13 +222,17 @@ enum thermal_access_mode { IBMACPI_THERMAL_NONE =3D 0, /* No thermal support */ IBMACPI_THERMAL_ACPI_TMP07, /* Use ACPI TMP0-7 */ IBMACPI_THERMAL_ACPI_UPDT, /* Use ACPI TMP0-7 with UPDT */ + IBMACPI_THERMAL_TPEC_8, /* Use ACPI EC regs, 8 sensors */ + IBMACPI_THERMAL_TPEC_16, /* Use ACPI EC regs, 16 sensors */ }; =20 -#define IBMACPI_MAX_THERMAL_SENSORS 8 /* Max thermal sensors supported *= / +#define IBMACPI_MAX_THERMAL_SENSORS 16 /* Max thermal sensors supported = */ struct ibm_thermal_sensors_struct { s32 temp[IBMACPI_MAX_THERMAL_SENSORS]; }; =20 +static int ibm_thinkpad_ec_found; + struct ibm_struct { char *name; char param[32]; @@ -1290,7 +1295,52 @@ static enum thermal_access_mode thermal_ =20 static int thermal_init(void) { - if (acpi_evalf(ec_handle, NULL, "TMP7", "qv")) { + u8 t, ta1, ta2; + int i; + int acpi_tmp7 =3D acpi_evalf(ec_handle, NULL, "TMP7", "qv"); + + if (ibm_thinkpad_ec_found && experimental) { + /* + * Direct EC access mode: sensors at registers + * 0x78-0x7F, 0xC0-0xC7. Registers return 0x00 for + * non-implemented, thermal sensors return 0x80 when + * not available + */ + + ta1 =3D ta2 =3D 0; + for (i =3D 0; i < 8; i++) { + if (likely(acpi_ec_read(0x78 + i, &t))) { + ta1 |=3D t; + } else { + ta1 =3D 0; + break; + } + if (likely(acpi_ec_read(0xC0 + i, &t))) { + ta2 |=3D t; + } else { + ta1 =3D 0; + break; + } + } + if (ta1 =3D=3D 0) { + /* This is sheer paranoia, but we handle it anyway */ + if (acpi_tmp7) { + printk(IBM_ERR + "ThinkPad ACPI EC access misbehaving, " + "falling back to ACPI TMPx access mode\n"); + thermal_read_mode =3D IBMACPI_THERMAL_ACPI_TMP07; + } else { + printk(IBM_ERR + "ThinkPad ACPI EC access misbehaving, " + "disabling thermal sensors access\n"); + thermal_read_mode =3D IBMACPI_THERMAL_NONE; + } + } else { + thermal_read_mode =3D + (ta2 !=3D 0) ? + IBMACPI_THERMAL_TPEC_16 : IBMACPI_THERMAL_TPEC_8; + } + } else if (acpi_tmp7) { if (acpi_evalf(ec_handle, NULL, "UPDT", "qv")) { /* 600e/x, 770e, 770x */ thermal_read_mode =3D IBMACPI_THERMAL_ACPI_UPDT; @@ -1309,12 +1359,30 @@ static int thermal_init(void) static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s) { int i, t; + s8 tmp; char tmpi[] =3D "TMPi"; =20 if (!s) return -EINVAL; =20 switch (thermal_read_mode) { +#if IBMACPI_MAX_THERMAL_SENSORS >=3D 16 + case IBMACPI_THERMAL_TPEC_16: + for (i =3D 0; i < 8; i++) { + if (!acpi_ec_read(0xC0 + i, &tmp)) + return -EIO; + s->temp[i + 8] =3D tmp * 1000; + } + /* fallthrough */ +#endif + case IBMACPI_THERMAL_TPEC_8: + for (i =3D 0; i < 8; i++) { + if (!acpi_ec_read(0x78 + i, &tmp)) + return -EIO; + s->temp[i] =3D tmp * 1000; + } + return (thermal_read_mode =3D=3D IBMACPI_THERMAL_TPEC_16) ? 16 : 8; + case IBMACPI_THERMAL_ACPI_UPDT: if (!acpi_evalf(ec_handle, NULL, "UPDT", "v")) return -EIO; @@ -2051,6 +2119,24 @@ static void acpi_ibm_exit(void) remove_proc_entry(IBM_DIR, acpi_root_dir); } =20 +static int __init check_dmi_for_ec(void) +{ + struct dmi_device *dev =3D NULL; + + /* + * ThinkPad T23 or newer, A31 or newer, R50e or newer, + * X32 or newer, all Z series; Some models must have an + * up-to-date BIOS or they will not be detected. + * + * See http://thinkwiki.org/wiki/List_of_DMI_IDs + */ + 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; @@ -2070,6 +2156,9 @@ static int __init acpi_ibm_init(void) 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); |
From: Henrique de M. H. <hm...@hm...> - 2006-11-22 20:14:10
|
From: Henrique de Moraes Holschuh <hm...@hm...> This patch consolidades all decisions regarding the strategy to be used t= o read thinkpad thermal sensors into a single enum, and refactors the thermal sensor reading code to use a much more readable (and easier to extend) switch() construct, in a separate function. Signed-off-by: Henrique de Moraes Holschuh <hm...@hm...> --- drivers/acpi/ibm_acpi.c | 90 ++++++++++++++++++++++++++++++++++-------= ------ 1 files changed, 65 insertions(+), 25 deletions(-) diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index a01bef7..067ff58 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -217,6 +217,17 @@ IBM_HANDLE(sfan, ec, "SFAN", /* 570 */ #define IBM_HKEY_HID "IBM0068" #define IBM_PCI_HID "PNP0A03" =20 +enum thermal_access_mode { + IBMACPI_THERMAL_NONE =3D 0, /* No thermal support */ + IBMACPI_THERMAL_ACPI_TMP07, /* Use ACPI TMP0-7 */ + IBMACPI_THERMAL_ACPI_UPDT, /* Use ACPI TMP0-7 with UPDT */ +}; + +#define IBMACPI_MAX_THERMAL_SENSORS 8 /* Max thermal sensors supported *= / +struct ibm_thermal_sensors_struct { + s32 temp[IBMACPI_MAX_THERMAL_SENSORS]; +}; + struct ibm_struct { char *name; char param[32]; @@ -1275,50 +1286,79 @@ static int acpi_ec_write(int i, u8 v) return 1; } =20 -static int thermal_tmp_supported; -static int thermal_updt_supported; +static enum thermal_access_mode thermal_read_mode; =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"); - - /* 600e/x, 770e, 770x */ - thermal_updt_supported =3D acpi_evalf(ec_handle, NULL, "UPDT", "qv"); + if (acpi_evalf(ec_handle, NULL, "TMP7", "qv")) { + if (acpi_evalf(ec_handle, NULL, "UPDT", "qv")) { + /* 600e/x, 770e, 770x */ + thermal_read_mode =3D IBMACPI_THERMAL_ACPI_UPDT; + } else { + /* Standard ACPI TMPx access, max 8 sensors */ + thermal_read_mode =3D IBMACPI_THERMAL_ACPI_TMP07; + } + } else { + /* temperatures not supported on 570, G4x, R30, R31, R32 */ + thermal_read_mode =3D IBMACPI_THERMAL_NONE; + } =20 return 0; } =20 -static int thermal_read(char *p) +static int thermal_get_sensors(struct ibm_thermal_sensors_struct *s) { - int len =3D 0; + int i, t; + char tmpi[] =3D "TMPi"; =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]; + if (!s) + return -EINVAL; =20 - if (thermal_updt_supported) - if (!acpi_evalf(ec_handle, NULL, "UPDT", "v")) + switch (thermal_read_mode) { + case IBMACPI_THERMAL_ACPI_UPDT: + if (!acpi_evalf(ec_handle, NULL, "UPDT", "v")) + return -EIO; + for (i =3D 0; i < 8; i++) { + tmpi[3] =3D '0' + i; + if (!acpi_evalf(ec_handle, &t, tmpi, "d")) return -EIO; + s->temp[i] =3D (t - 2732) * 100; + } + return 8; =20 + case IBMACPI_THERMAL_ACPI_TMP07: for (i =3D 0; i < 8; i++) { tmpi[3] =3D '0' + i; if (!acpi_evalf(ec_handle, &t, tmpi, "d")) return -EIO; - if (thermal_updt_supported) - tmp[i] =3D (t - 2732 + 5) / 10; - else - tmp[i] =3D t; + s->temp[i] =3D t * 1000; } + return 8; =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: + return 0; } +} + +static int thermal_read(char *p) +{ + int len =3D 0; + int n, i; + struct ibm_thermal_sensors_struct t; + + n =3D thermal_get_sensors(&t); + if (unlikely(n < 0)) + return n; + + len +=3D sprintf(p + len, "temperatures:\t"); + + if (n > 0) { + for (i =3D 0; i < (n - 1); i++) + len +=3D sprintf(p + len, "%d ", t.temp[i] / 1000); + len +=3D sprintf(p + len, "%d\n", t.temp[i] / 1000); + } else + len +=3D sprintf(p + len, "not supported\n"); =20 return len; } |
From: Henrique de M. H. <hm...@hm...> - 2006-11-22 20:14:02
|
From: Henrique de Moraes Holschuh <hm...@hm...> This patch documents the ThinkPad fan control strategies. Source of the data: 0. ibm-acpi source 1. DSDTs for various ThinkPads (770, X31, X40, X41, T43, A21m, T22) 2. http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issues 3. http://thinkwiki.org/wiki/How_to_control_fan_speed 4. Various threads about windows fan control utilities in thinkpads.com Signed-off-by: Henrique de Moraes Holschuh <hm...@hm...> --- drivers/acpi/ibm_acpi.c | 110 +++++++++++++++++++++++++++++++++++++++++= +++++- 1 files changed, 108 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index 3a5f662..dadd55b 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -205,7 +205,7 @@ IBM_HANDLE(led, ec, "SLED", /* 570 */ IBM_HANDLE(beep, ec, "BEEP"); /* all except R30, R31 */ IBM_HANDLE(ecrd, ec, "ECRD"); /* 570 */ IBM_HANDLE(ecwr, ec, "ECWR"); /* 570 */ -IBM_HANDLE(fans, ec, "FANS"); /* X31, X40 */ +IBM_HANDLE(fans, ec, "FANS"); /* X31, X40, X41 */ =20 IBM_HANDLE(gfan, ec, "GFAN", /* 570 */ "\\FSPD", /* 600e/x, 770e, 770x */ @@ -231,6 +231,106 @@ struct ibm_thermal_sensors_struct { s32 temp[IBMACPI_MAX_THERMAL_SENSORS]; }; =20 +/* + * FAN ACCESS MODES + * + * IBMACPI_FAN_RD_ACPI_GFAN: + * ACPI GFAN method: returns fan level + * + * see IBMACPI_FAN_WR_ACPI_SFAN + * EC 0x2f not available if GFAN exists + * + * IBMACPI_FAN_WR_ACPI_SFAN: + * ACPI SFAN method: sets fan level, 0 (stop) to 7 (max) + * + * EC 0x2f might be available *for reading*, but never for writing. + * + * IBMACPI_FAN_WR_TPEC: + * ThinkPad EC register 0x2f (HFSP): fan control loop mode Supported + * on almost all ThinkPads + * + * Fan speed changes of any sort (including those caused by the + * disengaged mode) are usually done slowly by the firmware as the + * maximum ammount of fan duty cycle change per second seems to be + * limited. + * + * Reading is not available if GFAN exists. + * Writing is not available if SFAN exists. + * + * Bits + * 7 automatic mode engaged; + * (default operation mode of the ThinkPad) + * fan level is ignored in this mode. + * 6 disengage mode (takes precedence over bit 7); + * not available on all thinkpads. May disable + * the tachometer, and speeds up fan to 100% duty-cycle, + * which speeds it up far above the standard RPM + * levels. It is not impossible that it could cause + * hardware damage. + * 5-3 unused in some models. Extra bits for fan level + * in others, but still useless as all values above + * 7 map to the same speed as level 7 in these models. + * 2-0 fan level (0..7 usually) + * 0x00 =3D stop + * 0x07 =3D max (set when temperatures critical) + * Some ThinkPads may have other levels, see + * IBMACPI_FAN_WR_ACPI_FANS (X31/X40/X41) + * + * FIRMWARE BUG: on some models, EC 0x2f might not be initialized at + * boot. Apparently the EC does not intialize it, so unless ACPI DSDT + * does so, its initial value is meaningless (0x07). + * + * For firmware bugs, refer to: + * http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issue= s + * + * ---- + * + * ThinkPad EC register 0x84 (LSB), 0x85 (MSB): + * Main fan tachometer reading (in RPM) + * + * This register is present on all ThinkPads with a new-style EC, and + * it is known not to be present on the A21m/e, and T22, as there is + * something else in offset 0x84 according to the ACPI DSDT. Other + * ThinkPads from this same time period (and earlier) probably lack the + * tachometer as well. + * + * Unfortunately a lot of ThinkPads with new-style ECs but whose firwmar= e + * was never fixed by IBM to report the EC firmware version string + * probably support the tachometer (like the early X models), so + * detecting it is quite hard. We need more data to know for sure. + * + * FIRMWARE BUG: always read 0x84 first, otherwise incorrect readings + * might result. + * + * FIRMWARE BUG: when EC 0x2f bit 6 is set (disengaged mode), this + * register is not invalidated in ThinkPads that disable tachometer + * readings. Thus, the tachometer readings go stale. + * + * For firmware bugs, refer to: + * http://thinkwiki.org/wiki/Embedded_Controller_Firmware#Firmware_Issue= s + * + * IBMACPI_FAN_WR_ACPI_FANS: + * ThinkPad X31, X40, X41. Not available in the X60. + * + * FANS ACPI handle: takes three arguments: low speed, medium speed, + * high speed. ACPI DSDT seems to map these three speeds to levels + * as follows: STOP LOW LOW MED MED HIGH HIGH HIGH HIGH + * (this map is stored on FAN0..FAN8 as "0,1,1,2,2,3,3,3,3") + * + * The speeds are stored on handles + * (FANA:FAN9), (FANC:FANB), (FANE:FAND). + * + * There are three default speed sets, acessible as handles: + * FS1L,FS1M,FS1H; FS2L,FS2M,FS2H; FS3L,FS3M,FS3H + * + * ACPI DSDT switches which set is in use depending on various + * factors. + * + * IBMACPI_FAN_WR_TPEC is also available and should be used to + * command the fan. The X31/X40/X41 seems to have 8 fan levels, + * but the ACPI tables just mention level 7. + */ + enum fan_status_access_mode { IBMACPI_FAN_NONE =3D 0, /* No fan status or control */ IBMACPI_FAN_RD_ACPI_GFAN, /* Use ACPI GFAN */ @@ -1722,7 +1822,7 @@ static int fan_init(void) /* all other models implement TP EC 0x2f control */ =20 if (fans_handle) { - /* X31, X40 */ + /* X31, X40, X41 */ fan_control_access_mode =3D IBMACPI_FAN_WR_ACPI_FANS; fan_control_commands |=3D @@ -1742,6 +1842,9 @@ static int fan_get_status(u8 *status) { u8 s; =20 + /* TODO: + * Add IBMACPI_FAN_RD_ACPI_FANS ? */ + switch (fan_status_access_mode) { case IBMACPI_FAN_RD_ACPI_GFAN: /* 570, 600e/x, 770e, 770x */ @@ -1950,6 +2053,9 @@ static int fan_write_cmd_speed(const cha { int speed; =20 + /* TODO: + * Support speed <low> <medium> <high> ? */ + if (sscanf(cmd, "speed %d", &speed) !=3D 1) return 0; =20 |
From: Henrique de M. H. <hm...@hm...> - 2006-11-22 20:13:52
|
From: Henrique de Moraes Holschuh <hm...@hm...> This patch cleans up the recently added backlight device support by Holge= r Macht <hm...@su...> to properly init and de-init itself using the ibms struct as the other "subdrivers" in ibm-acpi. Signed-off-by: Henrique de Moraes Holschuh <hm...@hm...> Cc: Holger Macht <hm...@su...> --- drivers/acpi/ibm_acpi.c | 50 +++++++++++++++++++++++++++++------------= ------ 1 files changed, 31 insertions(+), 19 deletions(-) diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index 576b09b..96e945c 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -395,7 +395,7 @@ struct ibm_struct { =20 static struct proc_dir_entry *proc_dir =3D NULL; =20 -static struct backlight_device *ibm_backlight_device; +static struct backlight_device *ibm_backlight_device =3D NULL; =20 #define onoff(status,bit) ((status) & (1 << (bit)) ? "on" : "off") #define enabled(status,bit) ((status) & (1 << (bit)) ? "enabled" : "disa= bled") @@ -1634,6 +1634,7 @@ static int brightness_get(struct backlig return -EIO; =20 level &=3D 0x7; + return level; } =20 @@ -1708,6 +1709,33 @@ static int brightness_update_status(stru return brightness_set(bd->props->brightness); } =20 +static struct backlight_properties ibm_backlight_data =3D { + .owner =3D THIS_MODULE, + .get_brightness =3D brightness_get, + .update_status =3D brightness_update_status, + .max_brightness =3D 7, +}; + +static int brightness_init(void) +{ + ibm_backlight_device =3D backlight_device_register("ibm", NULL, + &ibm_backlight_data); + if (IS_ERR(ibm_backlight_device)) { + printk(IBM_ERR "Could not register backlight device\n"); + return PTR_ERR(ibm_backlight_device); + } + + return 0; +} + +static void brightness_exit(void) +{ + if (ibm_backlight_device) { + backlight_device_unregister(ibm_backlight_device); + ibm_backlight_device =3D NULL; + } +} + static int volume_offset =3D 0x30; =20 static int volume_read(char *p) @@ -2370,6 +2398,8 @@ static struct ibm_struct ibms[] =3D { .name =3D "brightness", .read =3D brightness_read, .write =3D brightness_write, + .init =3D brightness_init, + .exit =3D brightness_exit, }, { .name =3D "volume", @@ -2632,20 +2662,10 @@ IBM_PARAM(brightness); IBM_PARAM(volume); IBM_PARAM(fan); =20 -static struct backlight_properties ibm_backlight_data =3D { - .owner =3D THIS_MODULE, - .get_brightness =3D brightness_get, - .update_status =3D brightness_update_status, - .max_brightness =3D 7, -}; - static void acpi_ibm_exit(void) { int i; =20 - if (ibm_backlight_device) - backlight_device_unregister(ibm_backlight_device); - for (i =3D ARRAY_SIZE(ibms) - 1; i >=3D 0; i--) ibm_exit(&ibms[i]); =20 @@ -2746,14 +2766,6 @@ static int __init acpi_ibm_init(void) } } =20 - ibm_backlight_device =3D backlight_device_register("ibm", NULL, - &ibm_backlight_data); - if (IS_ERR(ibm_backlight_device)) { - printk(IBM_ERR "Could not register ibm backlight device\n"); - ibm_backlight_device =3D NULL; - acpi_ibm_exit(); - } - return 0; } =20 |
From: Henrique de M. H. <hm...@hm...> - 2006-11-22 20:13:52
|
From: Henrique de Moraes Holschuh <hm...@hm...> This patch breaks fan_read mechanics into a generic function to get fan status and speed, and leaves only the procfs interface code in fan_read. Signed-off-by: Henrique de Moraes Holschuh <hm...@hm...> --- drivers/acpi/ibm_acpi.c | 78 ++++++++++++++++++++++++++++++++++++++++-= ------ 1 files changed, 66 insertions(+), 12 deletions(-) diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c index 5340562..bcb9680 100644 --- a/drivers/acpi/ibm_acpi.c +++ b/drivers/acpi/ibm_acpi.c @@ -1738,36 +1738,90 @@ static int fan_init(void) return 0; } =20 -static int fan_read(char *p) +static int fan_get_status(u8 *status) { - int len =3D 0; - u8 lo, hi, status; + u8 s; =20 switch (fan_status_access_mode) { case IBMACPI_FAN_RD_ACPI_GFAN: /* 570, 600e/x, 770e, 770x */ - if (unlikely(!acpi_evalf(gfan_handle, &status, NULL, "d"))) + + if (unlikely(!acpi_evalf(gfan_handle, &s, NULL, "d"))) return -EIO; =20 - len +=3D sprintf(p + len, "level:\t\t%d\n", status); + if (likely(status)) + *status =3D s & 0x07; =20 break; =20 case IBMACPI_FAN_RD_TPEC: /* all except 570, 600e/x, 770e, 770x */ - if (unlikely(!acpi_ec_read(fan_status_offset, &status))) + if (unlikely(!acpi_ec_read(fan_status_offset, &s))) return -EIO; - else - len +=3D sprintf(p + len, "status:\t\t%s\n", - enabled(status, 7)); =20 + if (likely(status)) + *status =3D s; + + break; + + default: + return -ENXIO; + } + + return 0; +} + +static int fan_get_speed(unsigned int *speed) +{ + u8 hi, lo; + + switch (fan_status_access_mode) { + case IBMACPI_FAN_RD_TPEC: + /* all except 570, 600e/x, 770e, 770x */ if (unlikely(!acpi_ec_read(fan_rpm_offset, &lo) || !acpi_ec_read(fan_rpm_offset + 1, &hi))) return -EIO; - else - len +=3D sprintf(p + len, "speed:\t\t%d\n", - (hi << 8) + lo); =20 + if (likely(speed)) + *speed =3D (hi << 8) | lo; + + break; + + default: + return -ENXIO; + } + + return 0; +} + +static int fan_read(char *p) +{ + int len =3D 0; + int rc; + u8 status; + unsigned int speed =3D 0; + + switch (fan_status_access_mode) { + case IBMACPI_FAN_RD_ACPI_GFAN: + /* 570, 600e/x, 770e, 770x */ + if ((rc =3D fan_get_status(&status)) < 0) + return rc; + + len +=3D sprintf(p + len, "level:\t\t%d\n", status); + + break; + + case IBMACPI_FAN_RD_TPEC: + /* all except 570, 600e/x, 770e, 770x */ + if ((rc =3D fan_get_status(&status)) < 0) + return rc; + + len +=3D sprintf(p + len, "status:\t\t%s\n", enabled(status, 7)); + + if ((rc =3D fan_get_speed(&speed)) < 0) + return rc; + + len +=3D sprintf(p + len, "speed:\t\t%d\n", speed); break; =20 case IBMACPI_FAN_NONE: |