diff mbox series

i2c: ismt: kill transaction in hardware on timeout

Message ID 20240819205125.92358-1-vasilykh@arista.com
State Accepted
Delegated to: Andi Shyti
Headers show
Series i2c: ismt: kill transaction in hardware on timeout | expand

Commit Message

Vasily Khoruzhick Aug. 19, 2024, 8:51 p.m. UTC
On Intel Denverton SoC ismt controller may enter weird state when
transaction gets stuck. It times out in the driver, but unless
transaction is explicitly killed in the controller, it won't be able to
perform new transactions anymore.

The issue is extremely difficult to reproduce and may take weeks of non-
stop smbus traffic.

Numerous hours with logic analyzer didn't yield any useful results, it
looks like the controller stops toggling SCK line, i.e. the issue is
likely in the controller, since device doesn't do clock stretching, so
nothing is driving SCK except the host.

Explicitly kill transaction on timeout to recover the controller from
this state.

Signed-off-by: Vasily Khoruzhick <vasilykh@arista.com>
---
 drivers/i2c/busses/i2c-ismt.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

Comments

Andi Shyti Sept. 9, 2024, 9:41 p.m. UTC | #1
Hi Vasily,

On Mon, Aug 19, 2024 at 01:51:04PM GMT, Vasily Khoruzhick wrote:
> On Intel Denverton SoC ismt controller may enter weird state when
> transaction gets stuck. It times out in the driver, but unless
> transaction is explicitly killed in the controller, it won't be able to
> perform new transactions anymore.
> 
> The issue is extremely difficult to reproduce and may take weeks of non-
> stop smbus traffic.
> 
> Numerous hours with logic analyzer didn't yield any useful results, it
> looks like the controller stops toggling SCK line, i.e. the issue is
> likely in the controller, since device doesn't do clock stretching, so
> nothing is driving SCK except the host.
> 
> Explicitly kill transaction on timeout to recover the controller from
> this state.
> 
> Signed-off-by: Vasily Khoruzhick <vasilykh@arista.com>

merged to i2c/i2c-host.

Thanks,
Andi
diff mbox series

Patch

diff --git a/drivers/i2c/busses/i2c-ismt.c b/drivers/i2c/busses/i2c-ismt.c
index 655b5d851c48..c93c02aa6ac8 100644
--- a/drivers/i2c/busses/i2c-ismt.c
+++ b/drivers/i2c/busses/i2c-ismt.c
@@ -381,6 +381,15 @@  static int ismt_process_desc(const struct ismt_desc *desc,
 	return -EIO;
 }
 
+/**
+ * ismt_kill_transaction() - kill current transaction
+ * @priv: iSMT private data
+ */
+static void ismt_kill_transaction(struct ismt_priv *priv)
+{
+	writel(ISMT_GCTRL_KILL, priv->smba + ISMT_GR_GCTRL);
+}
+
 /**
  * ismt_access() - process an SMBus command
  * @adap: the i2c host adapter
@@ -623,6 +632,7 @@  static int ismt_access(struct i2c_adapter *adap, u16 addr,
 		dma_unmap_single(dev, dma_addr, dma_size, dma_direction);
 
 	if (unlikely(!time_left)) {
+		ismt_kill_transaction(priv);
 		ret = -ETIMEDOUT;
 		goto out;
 	}