Unverified Commit 30792d12 authored by Saurav Sachidanand's avatar Saurav Sachidanand Committed by Andi Shyti
Browse files

i2c: tegra: make tegra_i2c_mutex_unlock() return void



tegra_i2c_mutex_unlock() returning an error that overwrites the transfer
result causes silent loss of I2C transfer errors. If the transfer failed
but the unlock succeeded, the error was lost and the function incorrectly
reported success.

Rather than propagating the unlock error (which is not actionable by the
caller - the I2C message may have been sent regardless), convert the
function to return void and WARN on the unexpected condition. If the
unlock fails, subsequent lock attempts will fail anyway, making the error
visible on the next transfer.

Fixes: 6077cfd7 ("i2c: tegra: Add support for SW mutex register")
Signed-off-by: default avatarSaurav Sachidanand <sauravsc@amazon.com>
Cc: <stable@vger.kernel.org> # v7.0+
Reviewed-by: default avatarJon Hunter <jonathanh@nvidia.com>
Acked-by: default avatarThierry Reding <treding@nvidia.com>
Signed-off-by: default avatarAndi Shyti <andi.shyti@kernel.org>
Link: https://lore.kernel.org/r/20260507221145.62183-3-sauravsc@amazon.com
parent 57cf4e8d
Loading
Loading
Loading
Loading
+6 −9
Original line number Diff line number Diff line
@@ -589,25 +589,22 @@ static int tegra_i2c_mutex_lock(struct tegra_i2c_dev *i2c_dev)
	return ret;
}

static int tegra_i2c_mutex_unlock(struct tegra_i2c_dev *i2c_dev)
static void tegra_i2c_mutex_unlock(struct tegra_i2c_dev *i2c_dev)
{
	unsigned int reg = i2c_dev->hw->regs->sw_mutex;
	u32 val, id;

	if (!i2c_dev->hw->has_mutex)
		return 0;
		return;

	val = readl(i2c_dev->base + reg);

	id = FIELD_GET(I2C_SW_MUTEX_GRANT, val);
	if (id && id != I2C_SW_MUTEX_ID_CCPLEX) {
		dev_warn(i2c_dev->dev, "unable to unlock mutex, mutex is owned by: %u\n", id);
		return -EPERM;
	}
	if (WARN(id && id != I2C_SW_MUTEX_ID_CCPLEX,
		 "unable to unlock mutex, mutex is owned by: %u\n", id))
		return;

	writel(0, i2c_dev->base + reg);

	return 0;
}

static void tegra_i2c_mask_irq(struct tegra_i2c_dev *i2c_dev, u32 mask)
@@ -1700,7 +1697,7 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
			break;
	}

	ret = tegra_i2c_mutex_unlock(i2c_dev);
	tegra_i2c_mutex_unlock(i2c_dev);
	pm_runtime_put(i2c_dev->dev);

	return ret ?: i;