applesmc read fail on mid-2012 Macbooks

The error is simple “applesmc: read arg fail” – this happens when trying to modprobe the applesmc module.

[   46.584969] applesmc: LSSB: read arg fail
[   46.672745] applesmc: LSSB: read arg fail
[   46.759992] applesmc: : read arg fail
[   46.847830] applesmc: : read arg fail
[   46.935599] applesmc: : read arg fail
[   47.023427] applesmc: : read arg fail
[   47.111244] applesmc: : read arg fail
[   47.199101] applesmc: : read arg fail

So I’ve been hacking around and reading forum threads when this genius over at Ubuntu forums came up with the solution – really simple.

The solution is a patch which actually only modifies one line of code – the constant telling the read from SMC to wait for feedback.

static int __wait_status(u8 val)
    int us;
    val = val & APPLESMC_STATUS_MASK;
    for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
        if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == val)
            return 0;
    return -EIO;

The constant to be changed is the APPLESMC_MIN_WAIT.

#define APPLESMC_MIN_WAIT     0x0040

is changed to

#define APPLESMC_MIN_WAIT     0x0010

This should take care of your problems!

Compiling the new module on Ubunutu

On Ubuntu systems you can get the kernel source by typing

sudo apt-get install linux-source

You can find the source in /usr/src. Uncompress it!

When you’ve applied the patch

index 0162f55..f41585e 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -54,7 +54,7 @@
/* wait up to 32 ms for a status change. */
-#define APPLESMC_MIN_WAIT	0x0040
+#define APPLESMC_MIN_WAIT	0x0010
#define APPLESMC_MAX_WAIT	0x8000

Then simply run

cd /usr/src/linux-source-x.x.x/linux-source-x-x-x/drivers/hwmon/
sudo make -C /lib/modules/$(uname -r)/build M=$(pwd) applesmc.ko
sudo insmod applesmc.ko
dmesg | grep applesmc

`dmesg | grep applesmc` should read something like
[ 70.969188] applesmc: key=375 fan=1 temp=22 acc=1 lux=2 kbd=1

Hope this works for you! :)