diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-10-29 14:44:03 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-10-29 14:44:03 -0700 |
commit | 57dbde63f2888af1be5111d369d124f4e659c0f8 (patch) | |
tree | 52b8e66f1f45f7076c2f65da56e78b0830efcfc6 /drivers/misc | |
parent | 134bf98c5596605af90f104716ef912e8f7eb56b (diff) | |
parent | 84de6e96e036dcfb18dded04a506b1dd72ba0e5b (diff) | |
download | linux-57dbde63f2888af1be5111d369d124f4e659c0f8.tar.bz2 |
Merge branch 'i2c/for-4.20' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c updates from Wolfram Sang:
"I2C has not so much stuff this time. Mostly driver enablement for new
SoCs, some driver bugfixes, and some cleanups"
* 'i2c/for-4.20' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (35 commits)
MAINTAINERS: add maintainer for Renesas RIIC driver
i2c: sh_mobile: Remove dummy runtime PM callbacks
i2c: uniphier-f: fix race condition when IRQ is cleared
i2c: uniphier-f: fix occasional timeout error
i2c: uniphier-f: make driver robust against concurrency
i2c: i2c-qcom-geni: Simplify irq handler
i2c: i2c-qcom-geni: Simplify tx/rx functions
i2c: designware: Set IRQF_NO_SUSPEND flag for all BYT and CHT controllers
i2c: mux: mlxcpld: simplify code to reach the adapter
i2c: mux: ltc4306: simplify code to reach the adapter
i2c: mux: pca954x: simplify code to reach the adapter
i2c: core: remove level of indentation in i2c_transfer
i2c: core: remove outdated DEBUG output
i2c: zx2967: use core to detect 'no zero length' quirk
i2c: tegra: use core to detect 'no zero length' quirk
i2c: qup: use core to detect 'no zero length' quirk
i2c: omap: use core to detect 'no zero length' quirk
i2c: Convert to using %pOFn instead of device_node.name
i2c: brcmstb: Allow enabling the driver on DSL SoCs
eeprom: at24: fix unexpected timeout under high load
...
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/eeprom/at24.c | 43 |
1 files changed, 22 insertions, 21 deletions
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c index 7e50e1d6f58c..636ed7149793 100644 --- a/drivers/misc/eeprom/at24.c +++ b/drivers/misc/eeprom/at24.c @@ -106,23 +106,6 @@ static unsigned int at24_write_timeout = 25; module_param_named(write_timeout, at24_write_timeout, uint, 0); MODULE_PARM_DESC(at24_write_timeout, "Time (in ms) to try writes (default 25)"); -/* - * Both reads and writes fail if the previous write didn't complete yet. This - * macro loops a few times waiting at least long enough for one entire page - * write to work while making sure that at least one iteration is run before - * checking the break condition. - * - * It takes two parameters: a variable in which the future timeout in jiffies - * will be stored and a temporary variable holding the time of the last - * iteration of processing the request. Both should be unsigned integers - * holding at least 32 bits. - */ -#define at24_loop_until_timeout(tout, op_time) \ - for (tout = jiffies + msecs_to_jiffies(at24_write_timeout), \ - op_time = 0; \ - op_time ? time_before(op_time, tout) : true; \ - usleep_range(1000, 1500), op_time = jiffies) - struct at24_chip_data { /* * these fields mirror their equivalents in @@ -308,13 +291,22 @@ static ssize_t at24_regmap_read(struct at24_data *at24, char *buf, /* adjust offset for mac and serial read ops */ offset += at24->offset_adj; - at24_loop_until_timeout(timeout, read_time) { + timeout = jiffies + msecs_to_jiffies(at24_write_timeout); + do { + /* + * The timestamp shall be taken before the actual operation + * to avoid a premature timeout in case of high CPU load. + */ + read_time = jiffies; + ret = regmap_bulk_read(regmap, offset, buf, count); dev_dbg(&client->dev, "read %zu@%d --> %d (%ld)\n", count, offset, ret, jiffies); if (!ret) return count; - } + + usleep_range(1000, 1500); + } while (time_before(read_time, timeout)); return -ETIMEDOUT; } @@ -358,14 +350,23 @@ static ssize_t at24_regmap_write(struct at24_data *at24, const char *buf, regmap = at24_client->regmap; client = at24_client->client; count = at24_adjust_write_count(at24, offset, count); + timeout = jiffies + msecs_to_jiffies(at24_write_timeout); + + do { + /* + * The timestamp shall be taken before the actual operation + * to avoid a premature timeout in case of high CPU load. + */ + write_time = jiffies; - at24_loop_until_timeout(timeout, write_time) { ret = regmap_bulk_write(regmap, offset, buf, count); dev_dbg(&client->dev, "write %zu@%d --> %d (%ld)\n", count, offset, ret, jiffies); if (!ret) return count; - } + + usleep_range(1000, 1500); + } while (time_before(write_time, timeout)); return -ETIMEDOUT; } |