[PATCH] Input: rmi_smbus - retry reading the SMBus version on -ENXIO

From: Markus Rathgeb

Date: Thu Nov 05 2026 - 15:57:52 EST


On a Dell Precision M3800 (Synaptics touchpad, PNP DLL060d, InterTouch on
i801 SMBus) the touchpad intermittently stays dead after resume from S3:

rmi4_smbus 8-002c: failed to get SMBus version number!
rmi4_physical rmi4-00: rmi_driver_reset_handler: Failed to read current IRQ mask.
rmi4_f01 rmi4-00.fn01: Failed to restore normal operation: -6.
rmi4_f01 rmi4-00.fn01: Resume failed with code -6.
rmi4_physical rmi4-00: Failed to suspend functions: -6
rmi4_smbus 8-002c: Failed to resume device: -6

This is not a recent regression. The system journal of this machine
(available since May 2024) shows it on every kernel series from v6.9 up to
v7.2, in about 18 of 377 S3 resumes (~5 %).

The resume ordering is correct: the PS/2 port is resumed first due to the
device link added by commit 7b1f781f2d24 ("Input: psmouse - set up
dependency between PS/2 and SMBus companions"), psmouse_deactivate()
succeeds, and rmi_smb_enable_smbus_mode() waits the 30 ms reset delay
added by commit 5030b2fe6aab ("Input: synaptics-rmi4 - handle reset delay
when using SMBus trsnsport"). Still, the device sometimes does not ACK the
version read yet. The error is not retried and rmi_smb_resume() ignores
it, so the touchpad remains unusable until the driver is re-bound.

Re-binding the driver (unbind/bind of the I2C client, no PS/2 command
involved) succeeds, and reading register 0xfd with i2cget before the
re-bind already returns a valid version. So the device does switch to
SMBus mode on its own, it just sometimes needs more than 30 ms.

Instead of increasing the fixed delay for all devices, retry the version
read on -ENXIO up to 10 times with 20 ms in between.

With this change, in 56 S3 cycles one resume needed a single retry (the
device answered after 30-50 ms) and none failed.

Link: https://lore.kernel.org/all/20230726025256.81174-1-jefferymiller@xxxxxxxxxx/
Signed-off-by: Markus Rathgeb <maggu2810@xxxxxxxxxxx>
---
drivers/input/rmi4/rmi_smbus.c | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/drivers/input/rmi4/rmi_smbus.c b/drivers/input/rmi4/rmi_smbus.c
index 8b61c2382297..93ecd6e14dee 100644
--- a/drivers/input/rmi4/rmi_smbus.c
+++ b/drivers/input/rmi4/rmi_smbus.c
@@ -22,6 +22,15 @@
#define RMI_SMB2_MAP_SIZE 8 /* 8 entry of 4 bytes each */
#define RMI_SMB2_MAP_FLAGS_WE 0x01

+/*
+ * After the PS/2 side (psmouse) has switched the device into SMBus mode it
+ * may take a while until the device ACKs on SMBus. On some devices (e.g. Dell
+ * Precision M3800) this sometimes takes longer than the reset delay after
+ * resume from S3, so retry the first access for a bounded amount of time.
+ */
+#define RMI_SMB_VERSION_RETRIES 10
+#define RMI_SMB_VERSION_RETRY_MS 20
+
struct mapping_table_entry {
__le16 rmiaddr;
u8 readcount;
@@ -43,14 +52,27 @@ static int rmi_smb_get_version(struct rmi_smb_xport *rmi_smb)
{
struct i2c_client *client = rmi_smb->client;
int retval;
+ int i;

/* Check if for SMBus new version device by reading version byte. */
- retval = i2c_smbus_read_byte_data(client, SMB_PROTOCOL_VERSION_ADDRESS);
+ for (i = 0; ; i++) {
+ retval = i2c_smbus_read_byte_data(client,
+ SMB_PROTOCOL_VERSION_ADDRESS);
+ if (retval != -ENXIO || i == RMI_SMB_VERSION_RETRIES)
+ break;
+ msleep(RMI_SMB_VERSION_RETRY_MS);
+ }
+
if (retval < 0) {
dev_err(&client->dev, "failed to get SMBus version number!\n");
return retval;
}

+ if (i)
+ dev_info(&client->dev,
+ "got SMBus version after %d retries (%d ms)\n",
+ i, i * RMI_SMB_VERSION_RETRY_MS);
+
return retval + 1;
}

--
2.56.0