Re: [PATCH v6 1/2] i2c: core: Add i2c_update_timeout() helper for dynamic transfer timeouts

Mukesh Savaliya <[email protected]> Wed, 22 Jul 2026 10:55:38 +0530
Newsgroups org.kernel.vger.linux-i2c,org.kernel.vger.linux-arm-msm,org.kernel.vger.linux-kernel
Message-ID <[email protected]>

On 7/20/2026 5:11 PM, Aniket Randive wrote:
> The transfer timeout for an I2C controller should reflect the actual
> message length and bus frequency rather than a static 1-second value.
> A static timeout causes unnecessary delays on error paths for short
> messages, and may be insufficient for very long transfers.
> 
in short write as should be relative to the bus speed and data length 
instead of any hard coded values.
> Add i2c_update_timeout() to i2c-core which computes a transfer-specific
> timeout and stores it directly in the standard adap->timeout field.  The
> formula accounts for 9 bits per byte (8 data + 1 ACK) at the configured
> bus frequency.  The caller supplies a safety multiplier and a minimum
> floor so that each driver retains full control over its timing policy
> without those values becoming public API.
> 
> Storing the result in adap->timeout makes it visible to all consumers of
> that field, including the arbitration-loss retry loop in __i2c_transfer().
> 
> Signed-off-by: Aniket Randive <[email protected]>
> ---
>   drivers/i2c/i2c-core-base.c | 24 ++++++++++++++++++++++++
>   include/linux/i2c.h         |  3 +++
>   2 files changed, 27 insertions(+)
> 
> diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
> index 3ec04787a737..3280652e20d8 100644
> --- a/drivers/i2c/i2c-core-base.c
> +++ b/drivers/i2c/i2c-core-base.c
> @@ -29,6 +29,7 @@
>   #include <linux/irq.h>
>   #include <linux/jump_label.h>
>   #include <linux/kernel.h>
> +#include <linux/math64.h>
>   #include <linux/module.h>
>   #include <linux/mutex.h>
>   #include <linux/of_device.h>
> @@ -2000,6 +2001,29 @@ void i2c_parse_fw_timings(struct device *dev, struct i2c_timings *t, bool use_de
>   }
>   EXPORT_SYMBOL_GPL(i2c_parse_fw_timings);
>   
can i2c-core-base.c calculate within and store into adap->timeout ? 
Current adap->timeout = HZ can be removed if we add coefficient and 
safety factor default ?

Any other thoughts ?

> +/**
> + * i2c_update_timeout - compute and set a dynamic transfer timeout on an adapter
> + * @adap: the i2c_adapter whose timeout field will be updated
> + * @bus_freq_hz: I2C bus clock frequency in Hz
> + * @len: transfer length in bytes
> + * @safety_coeff: multiplier applied over the theoretical wire time
> + * @min_usec: minimum timeout floor in microseconds
> + *
> + * Computes a transfer-specific timeout from the message length and bus
> + * frequency, applies a safety multiplier and a minimum floor, then stores
> + * the result in adap->timeout (in jiffies).  The caller supplies the policy
> + * constants so they remain internal to the driver.
> + */
> +void i2c_update_timeout(struct i2c_adapter *adap, u32 bus_freq_hz,
> +			size_t len, unsigned int safety_coeff,
> +			unsigned int min_usec)
> +{
> +	u64 bit_usec = mul_u64_u32_div(len * 9, USEC_PER_SEC, bus_freq_hz);
> +
> +	adap->timeout = usecs_to_jiffies(bit_usec * safety_coeff + min_usec);
> +}
> +EXPORT_SYMBOL_GPL(i2c_update_timeout);
why is this exported ? you have alrady added in i2c.h ?
> +
>   /* ------------------------------------------------------------------------- */
>   
>   int i2c_for_each_dev(void *data, int (*fn)(struct device *dev, void *data))
> diff --git a/include/linux/i2c.h b/include/linux/i2c.h
> index 14ab4d3055af..b52974eb7e58 100644
> --- a/include/linux/i2c.h
> +++ b/include/linux/i2c.h
> @@ -912,6 +912,9 @@ void i2c_put_adapter(struct i2c_adapter *adap);
>   unsigned int i2c_adapter_depth(struct i2c_adapter *adapter);
>   
>   void i2c_parse_fw_timings(struct device *dev, struct i2c_timings *t, bool use_defaults);
> +void i2c_update_timeout(struct i2c_adapter *adap, u32 bus_freq_hz,
> +			size_t len, unsigned int safety_coeff,
> +			unsigned int min_usec);
>   
>   /* Return the functionality mask */
>   static inline u32 i2c_get_functionality(struct i2c_adapter *adap)
>