i2c: i801: Add SMBUS_LEN_SENTINEL
authorHeiner Kallweit <hkallweit1@gmail.com>
Fri, 2 Feb 2024 07:04:06 +0000 (08:04 +0100)
committerAndi Shyti <andi.shyti@kernel.org>
Thu, 8 Feb 2024 17:06:46 +0000 (18:06 +0100)
Add a sentinel length value that is used to check whether we should
read and use the length value provided by the slave device.
This simplifies the currently used checks.

Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Reviewed-by: Andi Shyti <andi.shyti@kernel.org>
Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
drivers/i2c/busses/i2c-i801.c

index 24eb187dbc1f540c270fa850f6922be290e99165..15d2512883171a6856456dc8cdc823daea6c0036 100644 (file)
 #define STATUS_FLAGS           (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR | \
                                 STATUS_ERROR_FLAGS)
 
+#define SMBUS_LEN_SENTINEL (I2C_SMBUS_BLOCK_MAX + 1)
+
 /* Older devices have their ID defined in <linux/pci_ids.h> */
 #define PCI_DEVICE_ID_INTEL_COMETLAKE_SMBUS            0x02a3
 #define PCI_DEVICE_ID_INTEL_COMETLAKE_H_SMBUS          0x06a3
@@ -541,9 +543,12 @@ out:
 static void i801_isr_byte_done(struct i801_priv *priv)
 {
        if (priv->is_read) {
-               /* For SMBus block reads, length is received with first byte */
-               if (((priv->cmd & 0x1c) == I801_BLOCK_DATA) &&
-                   (priv->count == 0)) {
+               /*
+                * At transfer start i801_smbus_block_transaction() marks
+                * the block length as invalid. Check for this sentinel value
+                * and read the block length from SMBHSTDAT0.
+                */
+               if (priv->len == SMBUS_LEN_SENTINEL) {
                        priv->len = inb_p(SMBHSTDAT0(priv));
                        if (priv->len < 1 || priv->len > I2C_SMBUS_BLOCK_MAX) {
                                dev_err(&priv->pci_dev->dev,
@@ -698,8 +703,12 @@ static int i801_block_transaction_byte_by_byte(struct i801_priv *priv,
                if (status)
                        return status;
 
-               if (i == 1 && read_write == I2C_SMBUS_READ
-                && command != I2C_SMBUS_I2C_BLOCK_DATA) {
+               /*
+                * At transfer start i801_smbus_block_transaction() marks
+                * the block length as invalid. Check for this sentinel value
+                * and read the block length from SMBHSTDAT0.
+                */
+               if (len == SMBUS_LEN_SENTINEL) {
                        len = inb_p(SMBHSTDAT0(priv));
                        if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) {
                                dev_err(&priv->pci_dev->dev,
@@ -806,7 +815,8 @@ static int i801_smbus_block_transaction(struct i801_priv *priv, union i2c_smbus_
                                        u8 addr, u8 hstcmd, char read_write, int command)
 {
        if (read_write == I2C_SMBUS_READ && command == I2C_SMBUS_BLOCK_DATA)
-               data->block[0] = I2C_SMBUS_BLOCK_MAX;
+               /* Mark block length as invalid */
+               data->block[0] = SMBUS_LEN_SENTINEL;
        else if (data->block[0] < 1 || data->block[0] > I2C_SMBUS_BLOCK_MAX)
                return -EPROTO;