aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/applesmc.c
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@euromail.se>2008-10-18 23:27:38 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-20 11:52:35 -0400
commit84d2d7f2ee98dc9bd799790c89b5eb8280af2d37 (patch)
tree2cec712dcffd532ad8c82a24beae9bea497fa32a /drivers/hwmon/applesmc.c
parent05224091af06177c0ce7c1fae1f498455b47a6be (diff)
hwmon: applesmc: fix the 'wait status failed: c != 8' problem
On many Macbooks since mid 2007, the Pro, C2D and Air models, applesmc fails to read some or all SMC ports. This problem has various effects, such as flooded logfiles, malfunctioning temperature sensors, accelerometers failing to initialize, and difficulties getting backlight functionality to work properly. The root of the problem seems to be the command protocol. The current code sends out a command byte, then repeatedly polls for an ack before continuing to send or recieve data. From experiments leading to this patch, it seems the command protocol never quite worked or changed so that one now sends a command byte, waits a little bit, polls for an ack, and if it fails, repeats the whole thing by sending the command byte again. This patch implements a send_command function according to the new interpretation of the protocol, and should work also for earlier models. Signed-off-by: Henrik Rydberg <rydberg@euromail.se> Cc: Nicolas Boichat <nicolas@boichat.ch> Cc: Riki Oktarianto <rkoktarianto@gmail.com> Cc: Mark M. Hoffman <mhoffman@lightlink.com> Cc: Jean Delvare <khali@linux-fr.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/hwmon/applesmc.c')
-rw-r--r--drivers/hwmon/applesmc.c32
1 files changed, 24 insertions, 8 deletions
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index b401975bc0d..d5bd0cadbf3 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -191,6 +191,26 @@ static int __wait_status(u8 val)
191} 191}
192 192
193/* 193/*
194 * special treatment of command port - on newer macbooks, it seems necessary
195 * to resend the command byte before polling the status again. Callers must
196 * hold applesmc_lock.
197 */
198static int send_command(u8 cmd)
199{
200 int i;
201 for (i = 0; i < 1000; i++) {
202 outb(cmd, APPLESMC_CMD_PORT);
203 udelay(5);
204 if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == 0x0c)
205 return 0;
206 udelay(5);
207 }
208 printk(KERN_WARNING "applesmc: command failed: %x -> %x\n",
209 cmd, inb(APPLESMC_CMD_PORT));
210 return -EIO;
211}
212
213/*
194 * applesmc_read_key - reads len bytes from a given key, and put them in buffer. 214 * applesmc_read_key - reads len bytes from a given key, and put them in buffer.
195 * Returns zero on success or a negative error on failure. Callers must 215 * Returns zero on success or a negative error on failure. Callers must
196 * hold applesmc_lock. 216 * hold applesmc_lock.
@@ -205,8 +225,7 @@ static int applesmc_read_key(const char* key, u8* buffer, u8 len)
205 return -EINVAL; 225 return -EINVAL;
206 } 226 }
207 227
208 outb(APPLESMC_READ_CMD, APPLESMC_CMD_PORT); 228 if (send_command(APPLESMC_READ_CMD))
209 if (__wait_status(0x0c))
210 return -EIO; 229 return -EIO;
211 230
212 for (i = 0; i < 4; i++) { 231 for (i = 0; i < 4; i++) {
@@ -249,8 +268,7 @@ static int applesmc_write_key(const char* key, u8* buffer, u8 len)
249 return -EINVAL; 268 return -EINVAL;
250 } 269 }
251 270
252 outb(APPLESMC_WRITE_CMD, APPLESMC_CMD_PORT); 271 if (send_command(APPLESMC_WRITE_CMD))
253 if (__wait_status(0x0c))
254 return -EIO; 272 return -EIO;
255 273
256 for (i = 0; i < 4; i++) { 274 for (i = 0; i < 4; i++) {
@@ -284,8 +302,7 @@ static int applesmc_get_key_at_index(int index, char* key)
284 readkey[2] = index >> 8; 302 readkey[2] = index >> 8;
285 readkey[3] = index; 303 readkey[3] = index;
286 304
287 outb(APPLESMC_GET_KEY_BY_INDEX_CMD, APPLESMC_CMD_PORT); 305 if (send_command(APPLESMC_GET_KEY_BY_INDEX_CMD))
288 if (__wait_status(0x0c))
289 return -EIO; 306 return -EIO;
290 307
291 for (i = 0; i < 4; i++) { 308 for (i = 0; i < 4; i++) {
@@ -315,8 +332,7 @@ static int applesmc_get_key_type(char* key, char* type)
315{ 332{
316 int i; 333 int i;
317 334
318 outb(APPLESMC_GET_KEY_TYPE_CMD, APPLESMC_CMD_PORT); 335 if (send_command(APPLESMC_GET_KEY_TYPE_CMD))
319 if (__wait_status(0x0c))
320 return -EIO; 336 return -EIO;
321 337
322 for (i = 0; i < 4; i++) { 338 for (i = 0; i < 4; i++) {