Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

i2c: ismt: kill transaction in hardware on timeout

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>
Signed-off-by: Andi Shyti <andi.shyti@kernel.org>

authored by

Vasily Khoruzhick and committed by
Andi Shyti
46b2dfc0 66049b33

+10
+10
drivers/i2c/busses/i2c-ismt.c
··· 382 382 } 383 383 384 384 /** 385 + * ismt_kill_transaction() - kill current transaction 386 + * @priv: iSMT private data 387 + */ 388 + static void ismt_kill_transaction(struct ismt_priv *priv) 389 + { 390 + writel(ISMT_GCTRL_KILL, priv->smba + ISMT_GR_GCTRL); 391 + } 392 + 393 + /** 385 394 * ismt_access() - process an SMBus command 386 395 * @adap: the i2c host adapter 387 396 * @addr: address of the i2c/SMBus target ··· 632 623 dma_unmap_single(dev, dma_addr, dma_size, dma_direction); 633 624 634 625 if (unlikely(!time_left)) { 626 + ismt_kill_transaction(priv); 635 627 ret = -ETIMEDOUT; 636 628 goto out; 637 629 }