Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8c9398d1 authored by Henrik Rydberg's avatar Henrik Rydberg Committed by Linus Torvalds
Browse files

hwmon: applesmc: lighter wait mechanism, drastic improvement



The read fail ratio is sensitive to the delay between the first byte
written and the first byte read; apparently the sensors cannot be rushed.
Increasing the minimum wait time, without changing the total wait time,
improves the fail ratio from a 8% chance that any of the sensors fails in
one read, down to 0.4%, on a Macbook Air.  On a Macbook Pro 3,1, the
effect is even more apparent.  By reducing the number of status polls, the
ratio is further improved to below 0.1%.  Finally, increasing the total
wait time brings the fail ratio down to virtually zero.

Signed-off-by: default avatarHenrik Rydberg <rydberg@euromail.se>
Tested-by: default avatarBob McElrath <bob@mcelrath.org>
Cc: Nicolas Boichat <nicolas@boichat.ch>
Cc: "Mark M. Hoffman" <mhoffman@lightlink.com>
Cc: Jean Delvare <khali@linux-fr.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 07e8dbd3
Loading
Loading
Loading
Loading
+12 −10
Original line number Diff line number Diff line
@@ -49,6 +49,9 @@

#define APPLESMC_MAX_DATA_LENGTH 32

#define APPLESMC_MIN_WAIT	0x0040
#define APPLESMC_MAX_WAIT	0x8000

#define APPLESMC_STATUS_MASK	0x0f
#define APPLESMC_READ_CMD	0x10
#define APPLESMC_WRITE_CMD	0x11
@@ -172,25 +175,25 @@ static unsigned int key_at_index;
static struct workqueue_struct *applesmc_led_wq;

/*
 * __wait_status - Wait up to 10ms for the status port to get a certain value
 * __wait_status - Wait up to 32ms for the status port to get a certain value
 * (masked with 0x0f), returning zero if the value is obtained.  Callers must
 * hold applesmc_lock.
 */
static int __wait_status(u8 val)
{
	unsigned int i;
	int us;

	val = val & APPLESMC_STATUS_MASK;

	for (i = 0; i < 1000; i++) {
	for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
		udelay(us);
		if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == val) {
			if (debug)
				printk(KERN_DEBUG
					"Waited %d us for status %x\n",
						i*10, val);
					2 * us - APPLESMC_MIN_WAIT, val);
			return 0;
		}
		udelay(10);
	}

	printk(KERN_WARNING "applesmc: wait status failed: %x != %x\n",
@@ -206,13 +209,12 @@ static int __wait_status(u8 val)
 */
static int send_command(u8 cmd)
{
	int i;
	for (i = 0; i < 1000; i++) {
	int us;
	for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
		outb(cmd, APPLESMC_CMD_PORT);
		udelay(5);
		udelay(us);
		if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == 0x0c)
			return 0;
		udelay(5);
	}
	printk(KERN_WARNING "applesmc: command failed: %x -> %x\n",
		cmd, inb(APPLESMC_CMD_PORT));