All of lore.kernel.org
 help / color / mirror / Atom feed
From: Brad Campbell <brad@fnarfbargle.com>
To: Henrik Rydberg <rydberg@bitmath.org>
Cc: Arnd Bergmann <arnd@arndb.de>,
	linux-hwmon@vger.kernel.org,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	hns@goldelico.com, Guenter Roeck <linux@roeck-us.net>,
	Andreas Kemnade <andreas@kemnade.info>,
	Jean Delvare <jdelvare@suse.com>
Subject: Re: [PATCH] applesmc: Re-work SMC comms v2
Date: Sun, 8 Nov 2020 11:09:31 +1100	[thread overview]
Message-ID: <26d3f4f5-2e9a-cd20-1531-74cf44ef738c@fnarfbargle.com> (raw)
In-Reply-To: <5310c0ab-0f80-1f9e-8807-066223edae13@bitmath.org>

On 8/11/20 5:31 am, Henrik Rydberg wrote:
> On 2020-11-06 21:02, Henrik Rydberg wrote:
>>> So as it stands, it does not work at all. I will continue to check another machine, and see if I can get something working.
>>
>> On the MacBookAir3,1 the situation is somewhat better.
>>
>> The first three tree positions result in zero failures and 10 reads per second. The fourth yields zero failues and 11 reads per second, within the margin of similarity.
>>
>> So, the patch appears to have no apparent effect on the 3,1 series.
>>
>> Now onto fixing the 1,1 behavior.
> 
> Hi again,
> 
> This patch, v3, works for me, on both MBA1,1 and MBA3,1. Both machines yields 25 reads per second.
> 
> It turns out that the origin code has a case that was not carried over to the v2 patch; the command byte needs to be resent upon the wrong status code. I added that back. Also, there seems to be a basic response time that needs to be respected, so I added back a small fixed delay after each write operation. I also took the liberty to reduce the number of status reads, and clean up error handling. Checkpatch is happy with this version.
> 
> The code obviously needs to be retested on the other machines, but the logic still follows what you wrote, Brad, and I have also checked it against the VirtualSMC code. It appears to make sense, so hopefully there wont be additional issues.
> 
> Thanks,
> Henrik
> 

G'day Henrik,

Which kernel was this based on? It won't apply to my 5.9 tree.

I assume the sprinkling of udelay(APPLESMC_MIN_WAIT) means the SMC is
slow in getting its status register set up. Could we instead just put
a single one of those up-front in wait_status?

Any chance you could try this one? I've added a retry to send_command and 
added a single global APPLESMC_MIN_WAIT before each status read.

From looking at your modified send_command, it appears the trigger for a 
retry is sending a command and the SMC doing absolutely nothing. This
should do the same thing.

Interestingly enough, by adding the udelay to wait_status on my machine I've
gone from 24 reads/s to 50 reads/s.

I've left out the remainder of the cleanups. Once we get a minimally working
patch I was going to look at a few cleanups, and I have some patches pending
to allow writing to the SMC from userspace (for setting BCLM and BFCL mainly)


diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index a18887990f4a..2190de78b5f5 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -32,6 +32,7 @@
 #include <linux/hwmon.h>
 #include <linux/workqueue.h>
 #include <linux/err.h>
+#include <linux/bits.h>
 
 /* data port used by Apple SMC */
 #define APPLESMC_DATA_PORT	0x300
@@ -42,6 +43,11 @@
 
 #define APPLESMC_MAX_DATA_LENGTH 32
 
+/* Apple SMC status bits */
+#define SMC_STATUS_AWAITING_DATA  BIT(0) /* SMC has data waiting */
+#define SMC_STATUS_IB_CLOSED      BIT(1) /* Will ignore any input */
+#define SMC_STATUS_BUSY           BIT(2) /* Command in progress */
+
 /* wait up to 128 ms for a status change. */
 #define APPLESMC_MIN_WAIT	0x0010
 #define APPLESMC_RETRY_WAIT	0x0100
@@ -151,65 +157,73 @@ static unsigned int key_at_index;
 static struct workqueue_struct *applesmc_led_wq;
 
 /*
- * wait_read - Wait for a byte to appear on SMC port. Callers must
- * hold applesmc_lock.
+ * Wait for specific status bits with a mask on the SMC
+ * Used before and after writes, and before reads
  */
-static int wait_read(void)
+
+static int wait_status(u8 val, u8 mask)
 {
 	unsigned long end = jiffies + (APPLESMC_MAX_WAIT * HZ) / USEC_PER_SEC;
 	u8 status;
 	int us;
 
+	udelay(APPLESMC_MIN_WAIT);
 	for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
-		usleep_range(us, us * 16);
 		status = inb(APPLESMC_CMD_PORT);
-		/* read: wait for smc to settle */
-		if (status & 0x01)
+		if ((status & mask) == val)
 			return 0;
 		/* timeout: give up */
 		if (time_after(jiffies, end))
 			break;
+		usleep_range(us, us * 16);
 	}
-
-	pr_warn("wait_read() fail: 0x%02x\n", status);
 	return -EIO;
 }
 
 /*
- * send_byte - Write to SMC port, retrying when necessary. Callers
+ * send_byte_data - Write to SMC data port. Callers
  * must hold applesmc_lock.
+ * Parameter skip must be true on the last write of any
+ * command or it'll time out.
  */
-static int send_byte(u8 cmd, u16 port)
+
+static int send_byte_data(u8 cmd, u16 port, bool skip)
 {
-	u8 status;
-	int us;
-	unsigned long end = jiffies + (APPLESMC_MAX_WAIT * HZ) / USEC_PER_SEC;
+	int ret;
 
+	ret = wait_status(SMC_STATUS_BUSY, SMC_STATUS_BUSY | SMC_STATUS_IB_CLOSED);
+	if (ret)
+		return ret;
 	outb(cmd, port);
-	for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
-		usleep_range(us, us * 16);
-		status = inb(APPLESMC_CMD_PORT);
-		/* write: wait for smc to settle */
-		if (status & 0x02)
-			continue;
-		/* ready: cmd accepted, return */
-		if (status & 0x04)
-			return 0;
-		/* timeout: give up */
-		if (time_after(jiffies, end))
-			break;
-		/* busy: long wait and resend */
-		udelay(APPLESMC_RETRY_WAIT);
-		outb(cmd, port);
-	}
+	return wait_status(skip ? 0 : SMC_STATUS_BUSY, SMC_STATUS_BUSY);
+}
 
-	pr_warn("send_byte(0x%02x, 0x%04x) fail: 0x%02x\n", cmd, port, status);
-	return -EIO;
+static int send_byte(u8 cmd, u16 port)
+{
+	return send_byte_data(cmd, port, false);
 }
 
+/*
+ * send_command - Write a command to the SMC. Callers must hold applesmc_lock.
+ * If SMC is in undefined state, any new command write resets the state machine.
+ */
+
 static int send_command(u8 cmd)
 {
-	return send_byte(cmd, APPLESMC_CMD_PORT);
+	int ret;
+	int i;
+		
+	for (i=0; i < 16; i++) {
+		ret = wait_status(0, SMC_STATUS_IB_CLOSED);
+		if (ret)
+			return ret;
+	
+		outb(cmd, APPLESMC_CMD_PORT);
+		ret = wait_status(SMC_STATUS_BUSY, SMC_STATUS_BUSY);
+		if (!ret)
+			return ret;
+	}
+	return -EIO;
 }
 
 static int send_argument(const char *key)
@@ -239,7 +253,9 @@ static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len)
 	}
 
 	for (i = 0; i < len; i++) {
-		if (wait_read()) {
+		if (wait_status(SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY,
+				SMC_STATUS_AWAITING_DATA | SMC_STATUS_BUSY |
+				SMC_STATUS_IB_CLOSED)) {
 			pr_warn("%.4s: read data[%d] fail\n", key, i);
 			return -EIO;
 		}
@@ -250,7 +266,7 @@ static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len)
 	for (i = 0; i < 16; i++) {
 		udelay(APPLESMC_MIN_WAIT);
 		status = inb(APPLESMC_CMD_PORT);
-		if (!(status & 0x01))
+		if (!(status & SMC_STATUS_AWAITING_DATA))
 			break;
 		data = inb(APPLESMC_DATA_PORT);
 	}
@@ -275,7 +291,7 @@ static int write_smc(u8 cmd, const char *key, const u8 *buffer, u8 len)
 	}
 
 	for (i = 0; i < len; i++) {
-		if (send_byte(buffer[i], APPLESMC_DATA_PORT)) {
+		if (send_byte_data(buffer[i], APPLESMC_DATA_PORT, i == len - 1)) {
 			pr_warn("%s: write data fail\n", key);
 			return -EIO;
 		}



  reply	other threads:[~2020-11-08  0:11 UTC|newest]

Thread overview: 59+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-09-30  8:54 [REGRESSION] hwmon: (applesmc) avoid overlong udelay() Andreas Kemnade
2020-09-30 16:44 ` Guenter Roeck
2020-09-30 20:00   ` Arnd Bergmann
2020-10-01 22:22     ` Andreas Kemnade
2020-10-02  4:07       ` Guenter Roeck
2020-10-06  7:02         ` Andreas Kemnade
2020-11-02 23:56           ` Brad Campbell
2020-11-03  5:56             ` Brad Campbell
2020-11-04 13:20               ` Andreas Kemnade
2020-11-05  2:18                 ` Brad Campbell
2020-11-05  4:22                   ` Brad Campbell
2020-11-05  4:43                   ` Guenter Roeck
2020-11-05  5:05                     ` Brad Campbell
2020-11-05  5:26                       ` Guenter Roeck
2020-11-05  5:47                         ` [PATCH] applesmc: Re-work SMC comms v1 Brad Campbell
2020-11-05  7:26                           ` [PATCH] applesmc: Re-work SMC comms v2 Brad Campbell
2020-11-05  7:56                             ` Henrik Rydberg
2020-11-05  8:15                               ` Andreas Kemnade
2020-11-05  8:30                               ` Brad Campbell
2020-11-05 10:31                                 ` Henrik Rydberg
2020-11-06 16:26                                   ` Henrik Rydberg
2020-11-06 20:02                                     ` Henrik Rydberg
2020-11-07 18:31                                       ` Henrik Rydberg
2020-11-08  0:09                                         ` Brad Campbell [this message]
2020-11-08  8:22                                           ` Henrik Rydberg
2020-11-08  1:00                                         ` [PATCH v3] applesmc: Re-work SMC comms Brad Campbell
2020-11-08  8:35                                           ` Henrik Rydberg
2020-11-08 10:14                                             ` Henrik Rydberg
2020-11-08 11:57                                               ` Brad Campbell
2020-11-08 12:04                                                 ` Henrik Rydberg
2020-11-09 13:06                                                   ` Brad Campbell
2020-11-09 17:08                                                     ` Henrik Rydberg
2020-11-09 22:52                                                       ` Brad Campbell
2020-11-08 16:06                                               ` Guenter Roeck
2020-11-09  0:25                                                 ` Brad Campbell
2020-11-10  2:04                                                 ` Brad Campbell
2020-11-10  4:55                                                   ` Guenter Roeck
2020-11-10  5:40                                                     ` Brad Campbell
2020-11-10 16:02                                                       ` Guenter Roeck
2020-11-09  8:44                                               ` Andreas Kemnade
2020-11-09  9:51                                                 ` Brad Campbell
2020-11-11  3:37                                           ` [PATCH v4 0/1] " Brad Campbell
2020-11-11  4:55                                             ` [PATCH v1] applesmc: Cleanups on top of re-work comms Brad Campbell
2020-11-11  3:38                                           ` [PATCH v4 1/1] applesmc: Re-work SMC comms Brad Campbell
2020-11-11  5:56                                             ` Guenter Roeck
2020-11-11  7:05                                               ` Brad Campbell
2020-11-11 13:06                                               ` [PATCH v5 " Brad Campbell
2020-11-11 20:05                                                 ` Henrik Rydberg
2020-11-11 23:28                                                   ` Brad Campbell
2020-11-12  3:08                                                 ` [PATCH v6 " Brad Campbell
2020-11-12 17:20                                                   ` Guenter Roeck
2020-11-06 23:11                                     ` [PATCH] applesmc: Re-work SMC comms v2 Brad Campbell
2020-11-05  8:12                             ` Andreas Kemnade
2020-11-05 16:12                             ` Guenter Roeck
2020-11-06  0:02                               ` Brad Campbell
2020-11-06  3:08                                 ` Guenter Roeck
2020-11-09  9:27                           ` [PATCH] applesmc: Re-work SMC comms v1 kernel test robot
2020-11-09  9:27                             ` kernel test robot
2020-11-05  9:48                       ` [REGRESSION] hwmon: (applesmc) avoid overlong udelay() Arnd Bergmann

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=26d3f4f5-2e9a-cd20-1531-74cf44ef738c@fnarfbargle.com \
    --to=brad@fnarfbargle.com \
    --cc=andreas@kemnade.info \
    --cc=arnd@arndb.de \
    --cc=hns@goldelico.com \
    --cc=jdelvare@suse.com \
    --cc=linux-hwmon@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@roeck-us.net \
    --cc=rydberg@bitmath.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.