* Re: [RFC PATCH 1/2] i2c: smbus: Allow throttling of transfers to client devices
@ 2020-09-15 6:12 kernel test robot
0 siblings, 0 replies; 2+ messages in thread
From: kernel test robot @ 2020-09-15 6:12 UTC (permalink / raw)
To: kbuild
[-- Attachment #1: Type: text/plain, Size: 7039 bytes --]
CC: kbuild-all(a)lists.01.org
In-Reply-To: <20200914122811.3295678-2-andrew@aj.id.au>
References: <20200914122811.3295678-2-andrew@aj.id.au>
TO: Andrew Jeffery <andrew@aj.id.au>
Hi Andrew,
[FYI, it's a private test report for your RFC patch.]
[auto build test WARNING on wsa/i2c/for-next]
[also build test WARNING on hwmon/hwmon-next v5.9-rc5 next-20200914]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/Andrew-Jeffery/Throttle-I2C-transfers-to-UCD9000-devices/20200915-012501
base: https://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git i2c/for-next
:::::: branch date: 13 hours ago
:::::: commit date: 13 hours ago
config: mips-randconfig-s031-20200913 (attached as .config)
compiler: mips-linux-gcc (GCC) 9.3.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# apt-get install sparse
# sparse version: v0.6.2-191-g10164920-dirty
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' ARCH=mips
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
sparse warnings: (new ones prefixed by >>)
>> drivers/i2c/i2c-core-smbus.c:552:12: sparse: sparse: context imbalance in 'i2c_smbus_throttle_enter' - wrong count at exit
>> drivers/i2c/i2c-core-smbus.c:592:9: sparse: sparse: context imbalance in 'i2c_smbus_throttle_exit' - wrong count at exit
>> drivers/i2c/i2c-core-smbus.c:595:12: sparse: sparse: context imbalance in 'i2c_smbus_throttle_xfer' - wrong count at exit
# https://github.com/0day-ci/linux/commit/28892a041b063ffb23690eb11e5764ac0e675823
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review Andrew-Jeffery/Throttle-I2C-transfers-to-UCD9000-devices/20200915-012501
git checkout 28892a041b063ffb23690eb11e5764ac0e675823
vim +/i2c_smbus_throttle_enter +552 drivers/i2c/i2c-core-smbus.c
eef5ba1aa148ca Peter Rosin 2018-06-20 551
28892a041b063f Andrew Jeffery 2020-09-14 @552 static int i2c_smbus_throttle_enter(const struct i2c_client *client)
28892a041b063f Andrew Jeffery 2020-09-14 553 __acquires(&priv->throttle_lock)
28892a041b063f Andrew Jeffery 2020-09-14 554 {
28892a041b063f Andrew Jeffery 2020-09-14 555 struct i2c_client_priv *priv;
28892a041b063f Andrew Jeffery 2020-09-14 556 ktime_t earliest;
28892a041b063f Andrew Jeffery 2020-09-14 557 int rc;
28892a041b063f Andrew Jeffery 2020-09-14 558
28892a041b063f Andrew Jeffery 2020-09-14 559 priv = to_i2c_client_priv(client);
28892a041b063f Andrew Jeffery 2020-09-14 560
28892a041b063f Andrew Jeffery 2020-09-14 561 if (i2c_in_atomic_xfer_mode()) {
28892a041b063f Andrew Jeffery 2020-09-14 562 if (!mutex_trylock(&priv->throttle_lock))
28892a041b063f Andrew Jeffery 2020-09-14 563 return -EAGAIN;
28892a041b063f Andrew Jeffery 2020-09-14 564 } else {
28892a041b063f Andrew Jeffery 2020-09-14 565 rc = mutex_lock_interruptible(&priv->throttle_lock);
28892a041b063f Andrew Jeffery 2020-09-14 566 if (rc)
28892a041b063f Andrew Jeffery 2020-09-14 567 return rc;
28892a041b063f Andrew Jeffery 2020-09-14 568 }
28892a041b063f Andrew Jeffery 2020-09-14 569 earliest = ktime_add_us(priv->last, priv->delay_us);
28892a041b063f Andrew Jeffery 2020-09-14 570
28892a041b063f Andrew Jeffery 2020-09-14 571 if (priv->delay_us && ktime_before(ktime_get(), earliest)) {
28892a041b063f Andrew Jeffery 2020-09-14 572 if (i2c_in_atomic_xfer_mode()) {
28892a041b063f Andrew Jeffery 2020-09-14 573 mutex_unlock(&priv->throttle_lock);
28892a041b063f Andrew Jeffery 2020-09-14 574 return -EAGAIN;
28892a041b063f Andrew Jeffery 2020-09-14 575 }
28892a041b063f Andrew Jeffery 2020-09-14 576
28892a041b063f Andrew Jeffery 2020-09-14 577 usleep_range(priv->delay_us, 2 * priv->delay_us);
28892a041b063f Andrew Jeffery 2020-09-14 578 }
28892a041b063f Andrew Jeffery 2020-09-14 579
28892a041b063f Andrew Jeffery 2020-09-14 580 return 0;
28892a041b063f Andrew Jeffery 2020-09-14 581 }
28892a041b063f Andrew Jeffery 2020-09-14 582
28892a041b063f Andrew Jeffery 2020-09-14 583 static void i2c_smbus_throttle_exit(const struct i2c_client *client)
28892a041b063f Andrew Jeffery 2020-09-14 584 __releases(&priv->throttle_lock)
28892a041b063f Andrew Jeffery 2020-09-14 585 {
28892a041b063f Andrew Jeffery 2020-09-14 586 struct i2c_client_priv *priv;
28892a041b063f Andrew Jeffery 2020-09-14 587
28892a041b063f Andrew Jeffery 2020-09-14 588 priv = to_i2c_client_priv(client);
28892a041b063f Andrew Jeffery 2020-09-14 589
28892a041b063f Andrew Jeffery 2020-09-14 590 if (priv->delay_us)
28892a041b063f Andrew Jeffery 2020-09-14 591 priv->last = ktime_get();
28892a041b063f Andrew Jeffery 2020-09-14 @592 mutex_unlock(&priv->throttle_lock);
28892a041b063f Andrew Jeffery 2020-09-14 593 }
28892a041b063f Andrew Jeffery 2020-09-14 594
28892a041b063f Andrew Jeffery 2020-09-14 @595 static s32 i2c_smbus_throttle_xfer(const struct i2c_client *client,
28892a041b063f Andrew Jeffery 2020-09-14 596 char read_write, u8 command, int protocol,
28892a041b063f Andrew Jeffery 2020-09-14 597 union i2c_smbus_data *data)
28892a041b063f Andrew Jeffery 2020-09-14 598 {
28892a041b063f Andrew Jeffery 2020-09-14 599 s32 res;
28892a041b063f Andrew Jeffery 2020-09-14 600
28892a041b063f Andrew Jeffery 2020-09-14 601 res = i2c_smbus_throttle_enter(client);
28892a041b063f Andrew Jeffery 2020-09-14 602 if (res)
28892a041b063f Andrew Jeffery 2020-09-14 603 return res;
28892a041b063f Andrew Jeffery 2020-09-14 604
28892a041b063f Andrew Jeffery 2020-09-14 605 res = __i2c_lock_bus_helper(client->adapter);
28892a041b063f Andrew Jeffery 2020-09-14 606 if (!res)
28892a041b063f Andrew Jeffery 2020-09-14 607 res = __i2c_smbus_xfer(client->adapter, client->addr,
28892a041b063f Andrew Jeffery 2020-09-14 608 client->flags, read_write, command,
28892a041b063f Andrew Jeffery 2020-09-14 609 protocol, data);
28892a041b063f Andrew Jeffery 2020-09-14 610 i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT);
28892a041b063f Andrew Jeffery 2020-09-14 611
28892a041b063f Andrew Jeffery 2020-09-14 612 i2c_smbus_throttle_exit(client);
28892a041b063f Andrew Jeffery 2020-09-14 613
28892a041b063f Andrew Jeffery 2020-09-14 614 return res;
28892a041b063f Andrew Jeffery 2020-09-14 615 }
28892a041b063f Andrew Jeffery 2020-09-14 616
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 31785 bytes --]
^ permalink raw reply [flat|nested] 2+ messages in thread
* [RFC PATCH 0/2] Throttle I2C transfers to UCD9000 devices @ 2020-09-14 12:28 Andrew Jeffery 2020-09-14 12:28 ` [RFC PATCH 1/2] i2c: smbus: Allow throttling of transfers to client devices Andrew Jeffery 0 siblings, 1 reply; 2+ messages in thread From: Andrew Jeffery @ 2020-09-14 12:28 UTC (permalink / raw) To: linux-hwmon, linux-i2c; +Cc: linux, jdelvare, wsa, joel, linux-kernel Hello, While working with system designs making use of TI's UCD90320 Power Sequencer we've found that communication with the device isn't terribly reliable. It appears that back-to-back transfers where commands addressed to the device are put onto the bus with intervals between STOP and START in the neighbourhood of 250us or less can cause bad behaviour. This primarily happens during driver probe while scanning the device to determine its capabilities. We have observed the device causing excessive clock stretches and bus lockups, and also corruption of the device's volatile state (requiring it to be reset). The latter is particularly disruptive in that the controlled rails are brought down either by: 1. The corruption causing a fault condition, or 2. Asserting the device's reset line to recover A further observation is that pacing transfers to the device appears to mitigate the bad behaviour. We're in discussion with TI to better understand the limitations and at least get the behaviour documented. This short series implements the mitigation in terms of a throttle in the i2c_client associated with the device's driver. Before the first communication with the device in the probe() of ucd9000 we configure the i2c_client to throttle transfers with a minimum of a 1ms delay (with the delay exposed as a module parameter). The series is RFC for several reasons: The first is to sus out feelings on the general direction. The problem is pretty unfortunate - are there better ways to implement the mitigation? If there aren't, then: I'd like thoughts on whether we want to account for i2c-dev clients. Implementing throttling in i2c_client feels like a solution-by-proxy as the throttling is really a property of the targeted device, but we don't have a coherent representation between platform devices and devices associated with i2c-dev clients. At the moment we'd have to resort to address-based lookups for platform data stashed in the transfer functions. Next is that I've only implemented throttling for SMBus devices. I don't yet have a use-case for throttling non-SMBus devices so I'm not sure it's worth poking at it, but would appreciate thoughts there. Further, I've had a bit of a stab at dealing with atomic transfers that's not been tested. Hopefully it makes sense. Finally I'm also interested in feedback on exposing the control in a little more general manner than having to implement a module parameter in all drivers that want to take advantage of throttling. This isn't a big problem at the moment, but if anyone has thoughts there then I'm happy to poke at those too. Please review! Andrew Andrew Jeffery (2): i2c: smbus: Allow throttling of transfers to client devices hwmon: (pmbus/ucd9000) Throttle SMBus transfers to avoid poor behaviour drivers/hwmon/pmbus/ucd9000.c | 6 ++ drivers/i2c/i2c-core-base.c | 8 +- drivers/i2c/i2c-core-smbus.c | 149 +++++++++++++++++++++++++++------- drivers/i2c/i2c-core.h | 22 +++++ include/linux/i2c.h | 3 + 5 files changed, 157 insertions(+), 31 deletions(-) -- 2.25.1 ^ permalink raw reply [flat|nested] 2+ messages in thread
* [RFC PATCH 1/2] i2c: smbus: Allow throttling of transfers to client devices 2020-09-14 12:28 [RFC PATCH 0/2] Throttle I2C transfers to UCD9000 devices Andrew Jeffery @ 2020-09-14 12:28 ` Andrew Jeffery 0 siblings, 0 replies; 2+ messages in thread From: Andrew Jeffery @ 2020-09-14 12:28 UTC (permalink / raw) To: linux-hwmon, linux-i2c; +Cc: linux, jdelvare, wsa, joel, linux-kernel Some devices fail to cope in disastrous ways with the small command turn-around times enabled by in-kernel device drivers. Introduce per-client throttling of transfers to avoid these issues. Signed-off-by: Andrew Jeffery <andrew@aj.id.au> --- drivers/i2c/i2c-core-base.c | 8 +- drivers/i2c/i2c-core-smbus.c | 149 ++++++++++++++++++++++++++++------- drivers/i2c/i2c-core.h | 22 ++++++ include/linux/i2c.h | 3 + 4 files changed, 151 insertions(+), 31 deletions(-) diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 5ec082e2039d..d5a519bcadf9 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -867,13 +867,17 @@ int i2c_dev_irq_from_resources(const struct resource *resources, struct i2c_client * i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *info) { + struct i2c_client_priv *priv; struct i2c_client *client; int status; - client = kzalloc(sizeof *client, GFP_KERNEL); - if (!client) + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) return ERR_PTR(-ENOMEM); + mutex_init(&priv->throttle_lock); + client = &priv->client; + client->adapter = adap; client->dev.platform_data = info->platform_data; diff --git a/drivers/i2c/i2c-core-smbus.c b/drivers/i2c/i2c-core-smbus.c index f5c9787992e9..4a9692a37e1e 100644 --- a/drivers/i2c/i2c-core-smbus.c +++ b/drivers/i2c/i2c-core-smbus.c @@ -10,6 +10,7 @@ * SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com> and * Jean Delvare <jdelvare@suse.de> */ +#include <linux/delay.h> #include <linux/device.h> #include <linux/err.h> #include <linux/i2c.h> @@ -21,6 +22,9 @@ #define CREATE_TRACE_POINTS #include <trace/events/smbus.h> +static s32 i2c_smbus_throttle_xfer(const struct i2c_client *client, + char read_write, u8 command, int protocol, + union i2c_smbus_data *data); /* The SMBus parts */ @@ -95,9 +99,9 @@ s32 i2c_smbus_read_byte(const struct i2c_client *client) union i2c_smbus_data data; int status; - status = i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_READ, 0, - I2C_SMBUS_BYTE, &data); + status = i2c_smbus_throttle_xfer(client, I2C_SMBUS_READ, 0, + I2C_SMBUS_BYTE, &data); + return (status < 0) ? status : data.byte; } EXPORT_SYMBOL(i2c_smbus_read_byte); @@ -112,8 +116,8 @@ EXPORT_SYMBOL(i2c_smbus_read_byte); */ s32 i2c_smbus_write_byte(const struct i2c_client *client, u8 value) { - return i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL); + return i2c_smbus_throttle_xfer(client, I2C_SMBUS_WRITE, value, + I2C_SMBUS_BYTE, NULL); } EXPORT_SYMBOL(i2c_smbus_write_byte); @@ -130,9 +134,9 @@ s32 i2c_smbus_read_byte_data(const struct i2c_client *client, u8 command) union i2c_smbus_data data; int status; - status = i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_READ, command, - I2C_SMBUS_BYTE_DATA, &data); + status = i2c_smbus_throttle_xfer(client, I2C_SMBUS_READ, command, + I2C_SMBUS_BYTE_DATA, &data); + return (status < 0) ? status : data.byte; } EXPORT_SYMBOL(i2c_smbus_read_byte_data); @@ -150,10 +154,10 @@ s32 i2c_smbus_write_byte_data(const struct i2c_client *client, u8 command, u8 value) { union i2c_smbus_data data; + data.byte = value; - return i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_WRITE, command, - I2C_SMBUS_BYTE_DATA, &data); + return i2c_smbus_throttle_xfer(client, I2C_SMBUS_WRITE, command, + I2C_SMBUS_BYTE_DATA, &data); } EXPORT_SYMBOL(i2c_smbus_write_byte_data); @@ -170,9 +174,9 @@ s32 i2c_smbus_read_word_data(const struct i2c_client *client, u8 command) union i2c_smbus_data data; int status; - status = i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_READ, command, - I2C_SMBUS_WORD_DATA, &data); + status = i2c_smbus_throttle_xfer(client, I2C_SMBUS_READ, command, + I2C_SMBUS_WORD_DATA, &data); + return (status < 0) ? status : data.word; } EXPORT_SYMBOL(i2c_smbus_read_word_data); @@ -190,10 +194,10 @@ s32 i2c_smbus_write_word_data(const struct i2c_client *client, u8 command, u16 value) { union i2c_smbus_data data; + data.word = value; - return i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_WRITE, command, - I2C_SMBUS_WORD_DATA, &data); + return i2c_smbus_throttle_xfer(client, I2C_SMBUS_WRITE, command, + I2C_SMBUS_WORD_DATA, &data); } EXPORT_SYMBOL(i2c_smbus_write_word_data); @@ -218,9 +222,9 @@ s32 i2c_smbus_read_block_data(const struct i2c_client *client, u8 command, union i2c_smbus_data data; int status; - status = i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_READ, command, - I2C_SMBUS_BLOCK_DATA, &data); + status = i2c_smbus_throttle_xfer(client, I2C_SMBUS_READ, command, + I2C_SMBUS_BLOCK_DATA, &data); + if (status) return status; @@ -248,9 +252,8 @@ s32 i2c_smbus_write_block_data(const struct i2c_client *client, u8 command, length = I2C_SMBUS_BLOCK_MAX; data.block[0] = length; memcpy(&data.block[1], values, length); - return i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_WRITE, command, - I2C_SMBUS_BLOCK_DATA, &data); + return i2c_smbus_throttle_xfer(client, I2C_SMBUS_WRITE, command, + I2C_SMBUS_BLOCK_DATA, &data); } EXPORT_SYMBOL(i2c_smbus_write_block_data); @@ -264,9 +267,9 @@ s32 i2c_smbus_read_i2c_block_data(const struct i2c_client *client, u8 command, if (length > I2C_SMBUS_BLOCK_MAX) length = I2C_SMBUS_BLOCK_MAX; data.block[0] = length; - status = i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_READ, command, - I2C_SMBUS_I2C_BLOCK_DATA, &data); + status = i2c_smbus_throttle_xfer(client, I2C_SMBUS_READ, command, + I2C_SMBUS_I2C_BLOCK_DATA, &data); + if (status < 0) return status; @@ -284,9 +287,8 @@ s32 i2c_smbus_write_i2c_block_data(const struct i2c_client *client, u8 command, length = I2C_SMBUS_BLOCK_MAX; data.block[0] = length; memcpy(data.block + 1, values, length); - return i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_WRITE, command, - I2C_SMBUS_I2C_BLOCK_DATA, &data); + return i2c_smbus_throttle_xfer(client, I2C_SMBUS_WRITE, command, + I2C_SMBUS_I2C_BLOCK_DATA, &data); } EXPORT_SYMBOL(i2c_smbus_write_i2c_block_data); @@ -547,6 +549,71 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, } EXPORT_SYMBOL(i2c_smbus_xfer); +static int i2c_smbus_throttle_enter(const struct i2c_client *client) + __acquires(&priv->throttle_lock) +{ + struct i2c_client_priv *priv; + ktime_t earliest; + int rc; + + priv = to_i2c_client_priv(client); + + if (i2c_in_atomic_xfer_mode()) { + if (!mutex_trylock(&priv->throttle_lock)) + return -EAGAIN; + } else { + rc = mutex_lock_interruptible(&priv->throttle_lock); + if (rc) + return rc; + } + earliest = ktime_add_us(priv->last, priv->delay_us); + + if (priv->delay_us && ktime_before(ktime_get(), earliest)) { + if (i2c_in_atomic_xfer_mode()) { + mutex_unlock(&priv->throttle_lock); + return -EAGAIN; + } + + usleep_range(priv->delay_us, 2 * priv->delay_us); + } + + return 0; +} + +static void i2c_smbus_throttle_exit(const struct i2c_client *client) + __releases(&priv->throttle_lock) +{ + struct i2c_client_priv *priv; + + priv = to_i2c_client_priv(client); + + if (priv->delay_us) + priv->last = ktime_get(); + mutex_unlock(&priv->throttle_lock); +} + +static s32 i2c_smbus_throttle_xfer(const struct i2c_client *client, + char read_write, u8 command, int protocol, + union i2c_smbus_data *data) +{ + s32 res; + + res = i2c_smbus_throttle_enter(client); + if (res) + return res; + + res = __i2c_lock_bus_helper(client->adapter); + if (!res) + res = __i2c_smbus_xfer(client->adapter, client->addr, + client->flags, read_write, command, + protocol, data); + i2c_unlock_bus(client->adapter, I2C_LOCK_SEGMENT); + + i2c_smbus_throttle_exit(client); + + return res; +} + s32 __i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags, char read_write, u8 command, int protocol, union i2c_smbus_data *data) @@ -715,3 +782,27 @@ int of_i2c_setup_smbus_alert(struct i2c_adapter *adapter) } EXPORT_SYMBOL_GPL(of_i2c_setup_smbus_alert); #endif + +int i2c_smbus_throttle_client(struct i2c_client *client, + unsigned long delay_us) +{ + struct i2c_client_priv *priv; + int rc; + + priv = to_i2c_client_priv(client); + + if (i2c_in_atomic_xfer_mode()) { + if (!mutex_trylock(&priv->throttle_lock)) + return -EAGAIN; + } else { + rc = mutex_lock_interruptible(&priv->throttle_lock); + if (rc) + return rc; + } + priv->delay_us = delay_us; + priv->last = ktime_get(); + mutex_unlock(&priv->throttle_lock); + + return 0; +} +EXPORT_SYMBOL_GPL(i2c_smbus_throttle_client); diff --git a/drivers/i2c/i2c-core.h b/drivers/i2c/i2c-core.h index 8ce261167a2d..c763c6c431f9 100644 --- a/drivers/i2c/i2c-core.h +++ b/drivers/i2c/i2c-core.h @@ -4,6 +4,28 @@ */ #include <linux/rwsem.h> +#include <linux/i2c.h> +#include <linux/timekeeping.h> +#include <linux/kernel.h> +#include <linux/mutex.h> + +struct i2c_client_priv { + struct i2c_client client; + + /* + * Per-client access throttling, described in terms of microsecond + * delay between the end of the nth transfer and the start of the + * (n+1)th transfer. Used to manage devices which respond poorly to + * rapid back-to-back commands. + * + * Do it in a wrapper struct to preserve const-ness of the i2c_smbus_* + * interfaces. + */ + struct mutex throttle_lock; + unsigned long delay_us; + ktime_t last; +}; +#define to_i2c_client_priv(c) container_of(c, struct i2c_client_priv, client) struct i2c_devinfo { struct list_head list; diff --git a/include/linux/i2c.h b/include/linux/i2c.h index fc55ea41d323..adc91587d7fa 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -181,8 +181,11 @@ s32 i2c_smbus_write_i2c_block_data(const struct i2c_client *client, s32 i2c_smbus_read_i2c_block_data_or_emulated(const struct i2c_client *client, u8 command, u8 length, u8 *values); +int i2c_smbus_throttle_client(struct i2c_client *client, + unsigned long delay_us); int i2c_get_device_id(const struct i2c_client *client, struct i2c_device_identity *id); + #endif /* I2C */ /** -- 2.25.1 ^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2020-09-15 6:12 UTC | newest] Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2020-09-15 6:12 [RFC PATCH 1/2] i2c: smbus: Allow throttling of transfers to client devices kernel test robot -- strict thread matches above, loose matches on Subject: below -- 2020-09-14 12:28 [RFC PATCH 0/2] Throttle I2C transfers to UCD9000 devices Andrew Jeffery 2020-09-14 12:28 ` [RFC PATCH 1/2] i2c: smbus: Allow throttling of transfers to client devices Andrew Jeffery
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.