Commit 513fc69f authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull i2c fixes from Wolfram Sang:

 - qup: avoid potential hang when waiting for bus idle

 - tegra: improve ACPI reset error handling

 - virtio: use interruptible wait to prevent hang during transfer

* tag 'i2c-for-6.16-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux:
  i2c: qup: jump out of the loop in case of timeout
  i2c: virtio: Avoid hang by using interruptible completion wait
  i2c: tegra: Fix reset error handling with ACPI
parents 87488599 31f08841
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -452,8 +452,10 @@ static int qup_i2c_bus_active(struct qup_i2c_dev *qup, int len)
		if (!(status & I2C_STATUS_BUS_ACTIVE))
			break;

		if (time_after(jiffies, timeout))
		if (time_after(jiffies, timeout)) {
			ret = -ETIMEDOUT;
			break;
		}

		usleep_range(len, len * 2);
	}
+1 −23
Original line number Diff line number Diff line
@@ -607,7 +607,6 @@ static int tegra_i2c_wait_for_config_load(struct tegra_i2c_dev *i2c_dev)
static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
{
	u32 val, clk_divisor, clk_multiplier, tsu_thd, tlow, thigh, non_hs_mode;
	acpi_handle handle = ACPI_HANDLE(i2c_dev->dev);
	struct i2c_timings *t = &i2c_dev->timings;
	int err;

@@ -619,11 +618,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
	 * emit a noisy warning on error, which won't stay unnoticed and
	 * won't hose machine entirely.
	 */
	if (handle)
		err = acpi_evaluate_object(handle, "_RST", NULL, NULL);
	else
		err = reset_control_reset(i2c_dev->rst);

	err = device_reset(i2c_dev->dev);
	WARN_ON_ONCE(err);

	if (IS_DVC(i2c_dev))
@@ -1666,19 +1661,6 @@ static void tegra_i2c_parse_dt(struct tegra_i2c_dev *i2c_dev)
		i2c_dev->is_vi = true;
}

static int tegra_i2c_init_reset(struct tegra_i2c_dev *i2c_dev)
{
	if (ACPI_HANDLE(i2c_dev->dev))
		return 0;

	i2c_dev->rst = devm_reset_control_get_exclusive(i2c_dev->dev, "i2c");
	if (IS_ERR(i2c_dev->rst))
		return dev_err_probe(i2c_dev->dev, PTR_ERR(i2c_dev->rst),
				      "failed to get reset control\n");

	return 0;
}

static int tegra_i2c_init_clocks(struct tegra_i2c_dev *i2c_dev)
{
	int err;
@@ -1788,10 +1770,6 @@ static int tegra_i2c_probe(struct platform_device *pdev)

	tegra_i2c_parse_dt(i2c_dev);

	err = tegra_i2c_init_reset(i2c_dev);
	if (err)
		return err;

	err = tegra_i2c_init_clocks(i2c_dev);
	if (err)
		return err;
+8 −7
Original line number Diff line number Diff line
@@ -116,15 +116,16 @@ static int virtio_i2c_complete_reqs(struct virtqueue *vq,
	for (i = 0; i < num; i++) {
		struct virtio_i2c_req *req = &reqs[i];

		wait_for_completion(&req->completion);

		if (!failed && req->in_hdr.status != VIRTIO_I2C_MSG_OK)
		if (!failed) {
			if (wait_for_completion_interruptible(&req->completion))
				failed = true;
			else if (req->in_hdr.status != VIRTIO_I2C_MSG_OK)
				failed = true;
			else
				j++;
		}

		i2c_put_dma_safe_msg_buf(reqs[i].buf, &msgs[i], !failed);

		if (!failed)
			j++;
	}

	return j;