Skip to content

Commit 390b8f5

Browse files
svenpeter42Andi Shyti
authored andcommitted
i2c: pasemi: Improve timeout handling
The hardware (supposedly) has a 25ms timeout for clock stretching and the driver uses 100ms which should be plenty. The interrupt path however misses handling for errors while waiting for the completion and the polling path uses an open-coded readx_poll_timeout. Note that we drop reg_write(smbus, REG_SMSTA, status) while fixing those issues here which will be done anyway whenever the next transaction starts via pasemi_smb_clear. Signed-off-by: Sven Peter <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Andi Shyti <[email protected]>
1 parent 88fe307 commit 390b8f5

File tree

1 file changed

+29
-12
lines changed

1 file changed

+29
-12
lines changed

drivers/i2c/busses/i2c-pasemi-core.c

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <linux/delay.h>
1010
#include <linux/i2c.h>
1111
#include <linux/io.h>
12+
#include <linux/iopoll.h>
1213
#include <linux/kernel.h>
1314
#include <linux/module.h>
1415
#include <linux/pci.h>
@@ -52,6 +53,12 @@
5253
#define CTL_UJM BIT(8)
5354
#define CTL_CLK_M GENMASK(7, 0)
5455

56+
/*
57+
* The hardware (supposedly) has a 25ms timeout for clock stretching, thus
58+
* use 100ms here which should be plenty.
59+
*/
60+
#define PASEMI_TRANSFER_TIMEOUT_MS 100
61+
5562
static inline void reg_write(struct pasemi_smbus *smbus, int reg, int val)
5663
{
5764
dev_dbg(smbus->dev, "smbus write reg %x val %08x\n", reg, val);
@@ -90,33 +97,43 @@ static void pasemi_smb_clear(struct pasemi_smbus *smbus)
9097

9198
static int pasemi_smb_waitready(struct pasemi_smbus *smbus)
9299
{
93-
int timeout = 100;
94100
unsigned int status;
95101

96102
if (smbus->use_irq) {
97103
reinit_completion(&smbus->irq_completion);
98104
reg_write(smbus, REG_IMASK, SMSTA_XEN | SMSTA_MTN);
99-
wait_for_completion_timeout(&smbus->irq_completion, msecs_to_jiffies(100));
105+
int ret = wait_for_completion_timeout(
106+
&smbus->irq_completion,
107+
msecs_to_jiffies(PASEMI_TRANSFER_TIMEOUT_MS));
100108
reg_write(smbus, REG_IMASK, 0);
101109
status = reg_read(smbus, REG_SMSTA);
110+
111+
if (ret < 0) {
112+
dev_err(smbus->dev,
113+
"Completion wait failed with %d, status 0x%08x\n",
114+
ret, status);
115+
return ret;
116+
} else if (ret == 0) {
117+
dev_err(smbus->dev, "Timeout, status 0x%08x\n", status);
118+
return -ETIME;
119+
}
102120
} else {
103-
status = reg_read(smbus, REG_SMSTA);
104-
while (!(status & SMSTA_XEN) && timeout--) {
105-
msleep(1);
106-
status = reg_read(smbus, REG_SMSTA);
121+
int ret = readx_poll_timeout(
122+
ioread32, smbus->ioaddr + REG_SMSTA,
123+
status, status & SMSTA_XEN,
124+
USEC_PER_MSEC,
125+
USEC_PER_MSEC * PASEMI_TRANSFER_TIMEOUT_MS);
126+
127+
if (ret < 0) {
128+
dev_err(smbus->dev, "Timeout, status 0x%08x\n", status);
129+
return -ETIME;
107130
}
108131
}
109132

110133
/* Got NACK? */
111134
if (status & SMSTA_MTN)
112135
return -ENXIO;
113136

114-
if (timeout < 0) {
115-
dev_warn(smbus->dev, "Timeout, status 0x%08x\n", status);
116-
reg_write(smbus, REG_SMSTA, status);
117-
return -ETIME;
118-
}
119-
120137
/* Clear XEN */
121138
reg_write(smbus, REG_SMSTA, SMSTA_XEN);
122139

0 commit comments

Comments
 (0)