Linux I2C development
 help / color / mirror / Atom feed
* [PATCH v1 0/3] i2c: mlxbf: Fix master GW corruption
@ 2026-09-03 19:19 Chris Babroski
  2026-09-03 19:19 ` [PATCH v1 1/3] i2c: mlxbf: Fix master GW corruption from unmasked SMBus flags Chris Babroski
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Chris Babroski @ 2026-09-03 19:19 UTC (permalink / raw)
  To: andi.shyti, linux-i2c, linux-kernel; +Cc: cbabroski, davthompson

This patch series fixes a bug that corrupts the slave address used in read
phases and cleans up the code to prevent similar corruption scenarios from
occurring in the future.

When the MLXBF_I2C_F_SMBUS_BLOCK and/or MLXBF_I2C_F_SMBUS_PEC flags are set, the
flag bitmask values are shifted and written to the master gateway control
register instead of the single-bit flag values. This caused slave address
corruption in read phases (unlike write phases which use the data_desc[0] slave
address value).

Patch 1 fixes this corruption issue by converting the flags to booleans before
setting their values in the control register.

Patch 2 converts register field accesses from explicit shifts to
BIT()/GENMASK()/FIELD_PREP().

Patch 3 removes an unnecessary register write (dead code).

Chris Babroski (3):
  i2c: mlxbf: Fix master GW corruption from unmasked SMBus flags
  i2c: mlxbf: Use GENMASK()/FIELD_PREP() for GW fields
  i2c: mlxbf: Remove unused slave GW PEC handling

 drivers/i2c/busses/i2c-mlxbf.c | 40 +++++++++++++++++-----------------
 1 file changed, 20 insertions(+), 20 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH v1 1/3] i2c: mlxbf: Fix master GW corruption from unmasked SMBus flags
  2026-09-03 19:19 [PATCH v1 0/3] i2c: mlxbf: Fix master GW corruption Chris Babroski
@ 2026-09-03 19:19 ` Chris Babroski
  2026-09-03 19:20 ` [PATCH v1 2/3] i2c: mlxbf: Use GENMASK()/FIELD_PREP() for GW fields Chris Babroski
  2026-09-03 19:20 ` [PATCH v1 3/3] i2c: mlxbf: Remove unused slave GW PEC handling Chris Babroski
  2 siblings, 0 replies; 4+ messages in thread
From: Chris Babroski @ 2026-09-03 19:19 UTC (permalink / raw)
  To: andi.shyti, linux-i2c, linux-kernel; +Cc: cbabroski, davthompson

When the MLXBF_I2C_F_SMBUS_BLOCK and/or MLXBF_I2C_F_SMBUS_PEC flags are
set, the flag bitmask values are shifted and written to the master
gateway control register instead of the single-bit flag values. Shifting
and writing the bitmasks can corrupt adjacent bits in the master gateway
control register like the slave address used in read phases.

Convert the SMBus flags to boolean values before setting the master
gateway control register.

Signed-off-by: Chris Babroski <cbabroski@nvidia.com>
---
 drivers/i2c/busses/i2c-mlxbf.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/i2c/busses/i2c-mlxbf.c b/drivers/i2c/busses/i2c-mlxbf.c
index 24ccc4546ab8..93fc9f0ba72c 100644
--- a/drivers/i2c/busses/i2c-mlxbf.c
+++ b/drivers/i2c/busses/i2c-mlxbf.c
@@ -740,8 +740,8 @@ mlxbf_i2c_smbus_start_transaction(struct mlxbf_i2c_priv *priv,
 		 * submitted by the first operation only.
 		 */
 		if (op_idx == 0 && flags & MLXBF_I2C_F_SMBUS_OPERATION) {
-			block_en = flags & MLXBF_I2C_F_SMBUS_BLOCK;
-			pec_en = flags & MLXBF_I2C_F_SMBUS_PEC;
+			block_en = !!(flags & MLXBF_I2C_F_SMBUS_BLOCK);
+			pec_en = !!(flags & MLXBF_I2C_F_SMBUS_PEC);
 		}
 
 		if (flags & MLXBF_I2C_F_WRITE) {
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v1 2/3] i2c: mlxbf: Use GENMASK()/FIELD_PREP() for GW fields
  2026-09-03 19:19 [PATCH v1 0/3] i2c: mlxbf: Fix master GW corruption Chris Babroski
  2026-09-03 19:19 ` [PATCH v1 1/3] i2c: mlxbf: Fix master GW corruption from unmasked SMBus flags Chris Babroski
@ 2026-09-03 19:20 ` Chris Babroski
  2026-09-03 19:20 ` [PATCH v1 3/3] i2c: mlxbf: Remove unused slave GW PEC handling Chris Babroski
  2 siblings, 0 replies; 4+ messages in thread
From: Chris Babroski @ 2026-09-03 19:20 UTC (permalink / raw)
  To: andi.shyti, linux-i2c, linux-kernel; +Cc: cbabroski, davthompson

Replace the explicit shift amounts and rol32() calls used to build the
master and slave gateway control words with GENMASK()/FIELD_PREP().
This makes the field widths explicit and matches the style used
elsewhere in the kernel for register field access.

Also change the single-bit master GW PARSE_EXP and SEND_PEC control
bits to be set with a plain conditional OR instead of rol32(), since
moving a boolean into position via a mask is no longer needed.

Signed-off-by: Chris Babroski <cbabroski@nvidia.com>
---
 drivers/i2c/busses/i2c-mlxbf.c | 30 +++++++++++++++++-------------
 1 file changed, 17 insertions(+), 13 deletions(-)

diff --git a/drivers/i2c/busses/i2c-mlxbf.c b/drivers/i2c/busses/i2c-mlxbf.c
index 93fc9f0ba72c..2d2dc234db7a 100644
--- a/drivers/i2c/busses/i2c-mlxbf.c
+++ b/drivers/i2c/busses/i2c-mlxbf.c
@@ -219,7 +219,12 @@
 #define MLXBF_I2C_MASTER_BUSY_BIT         BIT(30) /* Busy bit. */
 #define MLXBF_I2C_MASTER_START_BIT        BIT(29) /* Control start. */
 #define MLXBF_I2C_MASTER_CTL_WRITE_BIT    BIT(28) /* Control write phase. */
+#define MLXBF_I2C_MASTER_WRITE_MASK       GENMASK(27, 21) /* Control write bytes */
+#define MLXBF_I2C_MASTER_SEND_PEC_BIT     BIT(20) /* Send PEC byte when set to 1 */
 #define MLXBF_I2C_MASTER_CTL_READ_BIT     BIT(19) /* Control read phase. */
+#define MLXBF_I2C_MASTER_SLV_ADDR_MASK    GENMASK(18, 12) /* Slave address */
+#define MLXBF_I2C_MASTER_PARSE_EXP_BIT    BIT(11) /* Control parse expected bytes */
+#define MLXBF_I2C_MASTER_READ_MASK        GENMASK(10, 4) /* Control read bytes */
 #define MLXBF_I2C_MASTER_STOP_BIT         BIT(3)  /* Control stop. */
 
 #define MLXBF_I2C_MASTER_ENABLE \
@@ -232,12 +237,6 @@
 #define MLXBF_I2C_MASTER_ENABLE_READ \
 	(MLXBF_I2C_MASTER_ENABLE | MLXBF_I2C_MASTER_CTL_READ_BIT)
 
-#define MLXBF_I2C_MASTER_WRITE_SHIFT      21 /* Control write bytes */
-#define MLXBF_I2C_MASTER_SEND_PEC_SHIFT   20 /* Send PEC byte when set to 1 */
-#define MLXBF_I2C_MASTER_PARSE_EXP_SHIFT  11 /* Control parse expected bytes */
-#define MLXBF_I2C_MASTER_SLV_ADDR_SHIFT   12 /* Slave address */
-#define MLXBF_I2C_MASTER_READ_SHIFT       4  /* Control read bytes */
-
 /* SMBus master GW Data descriptor. */
 #define MLXBF_I2C_MASTER_DATA_DESC_ADDR   0x80
 #define MLXBF_I2C_MASTER_DATA_DESC_SIZE   0x80 /* Size in bytes. */
@@ -288,7 +287,7 @@
 #define MLXBF_I2C_SLAVE_ENABLE \
 	(MLXBF_I2C_SLAVE_BUSY_BIT | MLXBF_I2C_SLAVE_WRITE_BIT)
 
-#define MLXBF_I2C_SLAVE_WRITE_BYTES_SHIFT 22 /* Number of bytes to write. */
+#define MLXBF_I2C_SLAVE_WRITE_BYTES_MASK  GENMASK(28, 22) /* Number of bytes to write. */
 #define MLXBF_I2C_SLAVE_SEND_PEC_SHIFT    21 /* Send PEC byte shift. */
 
 /* SMBus slave GW Data descriptor. */
@@ -643,14 +642,19 @@ static int mlxbf_i2c_smbus_enable(struct mlxbf_i2c_priv *priv, u8 slave,
 		command |= MLXBF_I2C_MASTER_STOP_BIT;
 	if (read) {
 		command |= MLXBF_I2C_MASTER_ENABLE_READ;
-		command |= rol32(len, MLXBF_I2C_MASTER_READ_SHIFT);
+		command |= FIELD_PREP(MLXBF_I2C_MASTER_READ_MASK, len);
 	} else {
 		command |= MLXBF_I2C_MASTER_ENABLE_WRITE;
-		command |= rol32(len, MLXBF_I2C_MASTER_WRITE_SHIFT);
+		command |= FIELD_PREP(MLXBF_I2C_MASTER_WRITE_MASK, len);
 	}
-	command |= rol32(slave, MLXBF_I2C_MASTER_SLV_ADDR_SHIFT);
-	command |= rol32(block_en, MLXBF_I2C_MASTER_PARSE_EXP_SHIFT);
-	command |= rol32(pec_en, MLXBF_I2C_MASTER_SEND_PEC_SHIFT);
+
+	if (block_en)
+		command |= MLXBF_I2C_MASTER_PARSE_EXP_BIT;
+
+	if (pec_en)
+		command |= MLXBF_I2C_MASTER_SEND_PEC_BIT;
+
+	command |= FIELD_PREP(MLXBF_I2C_MASTER_SLV_ADDR_MASK, slave);
 
 	/* Clear status bits. */
 	writel(0x0, priv->mst->io + MLXBF_I2C_SMBUS_MASTER_STATUS);
@@ -1888,7 +1892,7 @@ static int mlxbf_i2c_irq_send(struct mlxbf_i2c_priv *priv, u8 recv_bytes)
 
 	/* Prepare control word. */
 	control32 = MLXBF_I2C_SLAVE_ENABLE;
-	control32 |= rol32(write_size, MLXBF_I2C_SLAVE_WRITE_BYTES_SHIFT);
+	control32 |= FIELD_PREP(MLXBF_I2C_SLAVE_WRITE_BYTES_MASK, write_size);
 	control32 |= rol32(pec_en, MLXBF_I2C_SLAVE_SEND_PEC_SHIFT);
 
 	writel(control32, priv->slv->io + MLXBF_I2C_SMBUS_SLAVE_GW);
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH v1 3/3] i2c: mlxbf: Remove unused slave GW PEC handling
  2026-09-03 19:19 [PATCH v1 0/3] i2c: mlxbf: Fix master GW corruption Chris Babroski
  2026-09-03 19:19 ` [PATCH v1 1/3] i2c: mlxbf: Fix master GW corruption from unmasked SMBus flags Chris Babroski
  2026-09-03 19:20 ` [PATCH v1 2/3] i2c: mlxbf: Use GENMASK()/FIELD_PREP() for GW fields Chris Babroski
@ 2026-09-03 19:20 ` Chris Babroski
  2 siblings, 0 replies; 4+ messages in thread
From: Chris Babroski @ 2026-09-03 19:20 UTC (permalink / raw)
  To: andi.shyti, linux-i2c, linux-kernel; +Cc: cbabroski, davthompson

The slave gateway control word write always cleared its SEND_PEC bit,
since PEC is not supported on the slave path. Remove the dead pec_en
local variable, the corresponding register write, and the now-unused
MLXBF_I2C_SLAVE_SEND_PEC_SHIFT definition.

Signed-off-by: Chris Babroski <cbabroski@nvidia.com>
---
 drivers/i2c/busses/i2c-mlxbf.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/i2c/busses/i2c-mlxbf.c b/drivers/i2c/busses/i2c-mlxbf.c
index 2d2dc234db7a..deaf22df68d0 100644
--- a/drivers/i2c/busses/i2c-mlxbf.c
+++ b/drivers/i2c/busses/i2c-mlxbf.c
@@ -288,7 +288,6 @@
 	(MLXBF_I2C_SLAVE_BUSY_BIT | MLXBF_I2C_SLAVE_WRITE_BIT)
 
 #define MLXBF_I2C_SLAVE_WRITE_BYTES_MASK  GENMASK(28, 22) /* Number of bytes to write. */
-#define MLXBF_I2C_SLAVE_SEND_PEC_SHIFT    21 /* Send PEC byte shift. */
 
 /* SMBus slave GW Data descriptor. */
 #define MLXBF_I2C_SLAVE_DATA_DESC_ADDR   0x80
@@ -1822,7 +1821,7 @@ static struct i2c_client *mlxbf_i2c_get_slave_from_addr(
 static int mlxbf_i2c_irq_send(struct mlxbf_i2c_priv *priv, u8 recv_bytes)
 {
 	u8 data_desc[MLXBF_I2C_SLAVE_DATA_DESC_SIZE] = { 0 };
-	u8 write_size, pec_en, addr, value, byte_cnt;
+	u8 write_size, addr, value, byte_cnt;
 	struct i2c_client *slave;
 	u32 control32, data32;
 	int ret = 0;
@@ -1888,12 +1887,9 @@ static int mlxbf_i2c_irq_send(struct mlxbf_i2c_priv *priv, u8 recv_bytes)
 	mlxbf_i2c_smbus_write_data(priv, data_desc, byte_cnt,
 				   MLXBF_I2C_SLAVE_DATA_DESC_ADDR, false);
 
-	pec_en = 0; /* Disable PEC since it is not supported. */
-
 	/* Prepare control word. */
 	control32 = MLXBF_I2C_SLAVE_ENABLE;
 	control32 |= FIELD_PREP(MLXBF_I2C_SLAVE_WRITE_BYTES_MASK, write_size);
-	control32 |= rol32(pec_en, MLXBF_I2C_SLAVE_SEND_PEC_SHIFT);
 
 	writel(control32, priv->slv->io + MLXBF_I2C_SMBUS_SLAVE_GW);
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-09-03 19:20 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-03 19:19 [PATCH v1 0/3] i2c: mlxbf: Fix master GW corruption Chris Babroski
2026-09-03 19:19 ` [PATCH v1 1/3] i2c: mlxbf: Fix master GW corruption from unmasked SMBus flags Chris Babroski
2026-09-03 19:20 ` [PATCH v1 2/3] i2c: mlxbf: Use GENMASK()/FIELD_PREP() for GW fields Chris Babroski
2026-09-03 19:20 ` [PATCH v1 3/3] i2c: mlxbf: Remove unused slave GW PEC handling Chris Babroski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox