NAK/cmnt: [SRU][F:linux-bluefield][PATCH v2 1/1] UBUNTU: SAUCE: i2c-mlxbf.c: support lock mechanism

Tim Gardner tim.gardner at canonical.com
Wed Jul 20 12:49:07 UTC 2022


On 7/19/22 15:06, Asmaa Mnebhi wrote:
> Buglink: https://bugs.launchpad.net/bugs/1981105
> 
> Support the I2C lock mechanism, otherwise there could be
> unexpected behavior when an i2c bus is accessed by
> several entities like the linux driver, ATF driver and UEFI driver.
> 
> Make sure to pick up the ATF/UEFI image to accompany this change
> because at boot time ATF will ensure that the lock is released.
> 
> Signed-off-by: Asmaa Mnebhi <asmaa at nvidia.com>
> ---
>   drivers/i2c/busses/i2c-mlxbf.c | 38 ++++++++++++++++++++++++++++++----
>   1 file changed, 34 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-mlxbf.c b/drivers/i2c/busses/i2c-mlxbf.c
> index 0ac9e70244a7..fcb5bb587df1 100644
> --- a/drivers/i2c/busses/i2c-mlxbf.c
> +++ b/drivers/i2c/busses/i2c-mlxbf.c
> @@ -340,7 +340,8 @@ enum {
>    * Timeout is given in microsends. Note also that timeout handling is not
>    * exact.
>    */
> -#define SMBUS_TIMEOUT   (300 * 1000) /* 300ms */
> +#define SMBUS_TIMEOUT               (300 * 1000) /* 300ms */
> +#define SMBUS_LOCK_POLL_TIMEOUT           (300 * 1000) /* 300ms */
>   
>   /* Encapsulates timing parameters */
>   struct mlx_i2c_timings {
> @@ -573,6 +574,25 @@ static bool mlx_smbus_master_wait_for_idle(struct mlx_i2c_priv *priv)
>   	return false;
>   }
>   
> +/*
> + * wait for the lock to be released before acquiring it.
> + */
> +static bool mlx_smbus_master_lock(struct mlx_i2c_priv *priv)
> +{
> +	if (mlx_smbus_poll(priv->smbus->io, SMBUS_MASTER_GW,
> +			   1 << MASTER_LOCK_BIT_OFF, true,
> +			   SMBUS_LOCK_POLL_TIMEOUT))
> +		return true;
> +
> +	return false;
> +}
> +
> +static void mlx_smbus_master_unlock(struct mlx_i2c_priv *priv)
> +{
> +	/* Clear the gw to clear the lock */
> +	writel(0, priv->smbus->io + SMBUS_MASTER_GW);
> +}
> +
>   /*
>    * Poll SMBus master status and return transaction status,
>    * i.e. whether succeeded or failed. I2C and SMBus fault codes
> @@ -704,7 +724,7 @@ static int mlx_smbus_enable(struct mlx_i2c_priv *priv, u8 slave,
>   	/* Clear status bits  */
>   	smbus_write(priv->smbus->io, SMBUS_MASTER_STATUS, 0x0);
>   	/* Set the cause data */
> -	smbus_write(priv->smbus->io, I2C_CAUSE_OR_CLEAR_BITS, ~0x0);
> +	smbus_write(priv->mst_cause->io, I2C_CAUSE_OR_CLEAR_BITS, ~0x0);

This looks like a bug fix unrelated to the locking changes.

>   	/* Zero PEC byte */
>   	smbus_write(priv->smbus->io, SMBUS_MASTER_PEC, 0x0);
>   	/* Zero byte count    */
> @@ -744,7 +764,13 @@ static int mlx_smbus_start_transaction(struct mlx_i2c_priv *priv,
>   	slave     = request->slave & 0x7f;
>   	addr      = slave << 1;
>   
> -	/* First of all, check whether the HW is idle */
> +	/* Try to acquire the smbus gw lock before any reads of the GW register since
> +	 * a read sets the lock.
> +	 */
> +	if (WARN_ON(!mlx_smbus_master_lock(priv)))
> +		return -EBUSY;
> +

Does this function actually set the master lock bit ? It appears that it 
only polls the master lock bit until it returns 0 or 300 msec elapses. 
Does the HW have some unexplained behavior ? If so, then that is worthy 
of some explanation in the code.

> +	/* Check whether the HW is idle */
>   	if (WARN_ON(!mlx_smbus_master_wait_for_idle(priv)))
>   		return -EBUSY;

If the master lock bit is set, shouldn't it get released before 
returning an error ?

>   
> @@ -802,8 +828,10 @@ static int mlx_smbus_start_transaction(struct mlx_i2c_priv *priv,
>   	if (write_en) {
>   		ret = mlx_smbus_enable(priv, slave, write_len, block_en,
>   				       pec_en, 0);
> -		if (ret != 0)
> +		if (ret) {
> +			mlx_smbus_master_unlock(priv);
>   			return ret;
> +		}
>   	}
>   
>   	if (read_en) {
> @@ -830,6 +858,8 @@ static int mlx_smbus_start_transaction(struct mlx_i2c_priv *priv,
>   			    SMBUS_MASTER_FSM_PS_STATE_MASK);
>   	}
>   
> +	mlx_smbus_master_unlock(priv);
> +
>   	return ret;
>   }
>   


-- 
-----------
Tim Gardner
Canonical, Inc



More information about the kernel-team mailing list