Add linux v2.6.20-rc2, as most patches were merged in
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / releases / upstream / 2.6.20-rc2 / 0017-ACPI-ibm-acpi-workaround-for-EC-0x2f-initialization-bug.txt
blob082f53e7bfa7b18e7e33614304005ce72580d858
1 From 778b4d742b210b9cac31f223527f30f1fc70312b Mon Sep 17 00:00:00 2001
2 From: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
3 Date: Fri, 24 Nov 2006 11:47:14 -0200
4 Subject: [PATCH 17/28] ACPI: ibm-acpi: workaround for EC 0x2f initialization bug
6 A few ThinkPads fail to initialize EC register 0x2f both in the EC
7 firmware and ACPI DSDT.  If the BIOS and the ACPI DSDT also do not
8 initialize it, then the initial status of that register does not
9 correspond to reality.
11 On all reported buggy machines, EC 0x2f will read 0x07 (fan level 7) upon
12 cold boot, when the EC is actually in mode 0x80 (auto mode).  Since
13 returning a text string ("unknown") would break a number of userspace
14 programs, instead we correct the reading for the most probably correct
15 answer, and return it is in auto mode.
17 The workaround flags the status and level as unknown on module load/kernel
18 boot, until we are certain at least one fan control command was issued,
19 either by us, or by something else.
21 We don't work around the bug by doing a "fan enable" at module
22 load/startup (which would initialize the EC register) because it is not
23 known if these ThinkPad ACPI DSDT might have set the fan to level 7
24 instead of "auto" (we don't know if they can do this or not) due to a
25 thermal condition, and we don't want to override that, should they be
26 capable of it.
28 We should be setting the workaround flag to "status known" upon resume, as
29 both reports and a exaustive search on the DSDT tables at acpi.sf.net show
30 that the DSDTs always enable the fan on resume, thus working around the
31 bug.  But since we don't have suspend/resume handlers in ibm-acpi yet and
32 the "EC register 0x2f was modified" logic is likely to catch the change
33 anyway, we don't.
35 Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br>
36 ---
37  drivers/acpi/ibm_acpi.c |   53 +++++++++++++++++++++++++++++++++++++++++++---
38  1 files changed, 49 insertions(+), 4 deletions(-)
40 diff --git a/drivers/acpi/ibm_acpi.c b/drivers/acpi/ibm_acpi.c
41 index 3c091c4..56743c5 100644
42 --- a/drivers/acpi/ibm_acpi.c
43 +++ b/drivers/acpi/ibm_acpi.c
44 @@ -362,7 +362,7 @@ enum {                                      /* Fan control constants */
45                                                  * control */
46  };
48 -static char* ibm_thinkpad_ec_found = NULL;
49 +static char *ibm_thinkpad_ec_found = NULL;
51  struct ibm_struct {
52         char *name;
53 @@ -1794,13 +1794,15 @@ static enum fan_status_access_mode fan_status_access_mode;
54  static enum fan_control_access_mode fan_control_access_mode;
55  static enum fan_control_commands fan_control_commands;
57 +static int fan_control_status_known;
58 +static u8 fan_control_initial_status;
60  static int fan_init(void)
61  {
62 -       u8 status;
64         fan_status_access_mode = IBMACPI_FAN_NONE;
65         fan_control_access_mode = IBMACPI_FAN_WR_NONE;
66         fan_control_commands = 0;
67 +       fan_control_status_known = 1;
69         if (gfan_handle) {
70                 /* 570, 600e/x, 770e, 770x */
71 @@ -1808,8 +1810,33 @@ static int fan_init(void)
72         } else {
73                 /* all other ThinkPads: note that even old-style
74                  * ThinkPad ECs supports the fan control register */
75 -               if (likely(acpi_ec_read(fan_status_offset, &status))) {
76 +               if (likely(acpi_ec_read(fan_status_offset,
77 +                                       &fan_control_initial_status))) {
78                         fan_status_access_mode = IBMACPI_FAN_RD_TPEC;
80 +                       /* In some ThinkPads, neither the EC nor the ACPI
81 +                        * DSDT initialize the fan status, and it ends up
82 +                        * being set to 0x07 when it *could* be either
83 +                        * 0x07 or 0x80.
84 +                        *
85 +                        * Enable for TP-1Y (T43), TP-78 (R51e),
86 +                        * TP-76 (R52), TP-70 (T43, R52), which are known
87 +                        * to be buggy. */
88 +                       if (fan_control_initial_status == 0x07 &&
89 +                           ibm_thinkpad_ec_found &&
90 +                           ((ibm_thinkpad_ec_found[0] == '1' &&
91 +                             ibm_thinkpad_ec_found[1] == 'Y') ||
92 +                            (ibm_thinkpad_ec_found[0] == '7' &&
93 +                             (ibm_thinkpad_ec_found[1] == '6' ||
94 +                              ibm_thinkpad_ec_found[1] == '8' ||
95 +                              ibm_thinkpad_ec_found[1] == '0'))
96 +                           )) {
97 +                               printk(IBM_NOTICE
98 +                                      "fan_init: initial fan status is "
99 +                                      "unknown, assuming it is in auto "
100 +                                      "mode\n");
101 +                               fan_control_status_known = 0;
102 +                       }
103                 } else {
104                         printk(IBM_ERR
105                                "ThinkPad ACPI EC access misbehaving, "
106 @@ -1930,9 +1957,21 @@ static int fan_read(char *p)
107                 if ((rc = fan_get_status(&status)) < 0)
108                         return rc;
110 +               if (unlikely(!fan_control_status_known)) {
111 +                       if (status != fan_control_initial_status)
112 +                               fan_control_status_known = 1;
113 +                       else
114 +                               /* Return most likely status. In fact, it
115 +                                * might be the only possible status */
116 +                               status = IBMACPI_FAN_EC_AUTO;
117 +               }
119                 len += sprintf(p + len, "status:\t\t%s\n",
120                                (status != 0) ? "enabled" : "disabled");
122 +               /* No ThinkPad boots on disengaged mode, we can safely
123 +                * assume the tachometer is online if fan control status
124 +                * was unknown */
125                 if ((rc = fan_get_speed(&speed)) < 0)
126                         return rc;
128 @@ -1997,6 +2036,8 @@ static int fan_set_level(int level)
130                 if (!acpi_ec_write(fan_status_offset, level))
131                         return -EIO;
132 +               else
133 +                       fan_control_status_known = 1;
134                 break;
136         default:
137 @@ -2022,6 +2063,8 @@ static int fan_set_enable(void)
139                 if (!acpi_ec_write(fan_status_offset, s))
140                         return -EIO;
141 +               else
142 +                       fan_control_status_known = 1;
143                 break;
145         case IBMACPI_FAN_WR_ACPI_SFAN:
146 @@ -2051,6 +2094,8 @@ static int fan_set_disable(void)
147         case IBMACPI_FAN_WR_TPEC:
148                 if (!acpi_ec_write(fan_status_offset, 0x00))
149                         return -EIO;
150 +               else
151 +                       fan_control_status_known = 1;
152                 break;
154         case IBMACPI_FAN_WR_ACPI_SFAN:
155 -- 
156 1.4.4.2