Commit f023605d authored by Hans de Goede's avatar Hans de Goede Committed by Jiri Kosina
Browse files

HID: i2c-hid: Fold i2c_hid_execute_reset() into i2c_hid_hwreset()



i2c_hid_hwreset() is the only caller of i2c_hid_execute_reset(),
fold the latter into the former.

This is a preparation patch for removing the need for
I2C_HID_QUIRK_NO_IRQ_AFTER_RESET by making i2c-hid behave
more like Windows.

No functional changes intended.

Reviewed-by: default avatarDouglas Anderson <dianders@chromium.org>
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.com>
parent 1f342790
Loading
Loading
Loading
Loading
+30 −43
Original line number Diff line number Diff line
@@ -426,12 +426,23 @@ static int i2c_hid_set_power(struct i2c_hid *ihid, int power_state)
	return ret;
}

static int i2c_hid_execute_reset(struct i2c_hid *ihid)
static int i2c_hid_hwreset(struct i2c_hid *ihid)
{
	size_t length = 0;
	int ret;

	i2c_hid_dbg(ihid, "resetting...\n");
	i2c_hid_dbg(ihid, "%s\n", __func__);

	/*
	 * This prevents sending feature reports while the device is
	 * being reset. Otherwise we may lose the reset complete
	 * interrupt.
	 */
	mutex_lock(&ihid->reset_lock);

	ret = i2c_hid_set_power(ihid, I2C_HID_PWR_ON);
	if (ret)
		goto err_unlock;

	/* Prepare reset command. Command register goes first. */
	*(__le16 *)ihid->cmdbuf = ihid->hdesc.wCommandRegister;
@@ -444,59 +455,35 @@ static int i2c_hid_execute_reset(struct i2c_hid *ihid)

	ret = i2c_hid_xfer(ihid, ihid->cmdbuf, length, NULL, 0);
	if (ret) {
		dev_err(&ihid->client->dev, "failed to reset device.\n");
		goto out;
		dev_err(&ihid->client->dev,
			"failed to reset device: %d\n", ret);
		goto err_clear_reset;
	}

	i2c_hid_dbg(ihid, "%s: waiting...\n", __func__);

	if (ihid->quirks & I2C_HID_QUIRK_NO_IRQ_AFTER_RESET) {
		msleep(100);
		goto out;
	}

	i2c_hid_dbg(ihid, "%s: waiting...\n", __func__);
	if (!wait_event_timeout(ihid->wait,
		clear_bit(I2C_HID_RESET_PENDING, &ihid->flags);
	} else if (!wait_event_timeout(ihid->wait,
				       !test_bit(I2C_HID_RESET_PENDING, &ihid->flags),
				       msecs_to_jiffies(5000))) {
		ret = -ENODATA;
		goto out;
		goto err_clear_reset;
	}
	i2c_hid_dbg(ihid, "%s: finished.\n", __func__);

out:
	clear_bit(I2C_HID_RESET_PENDING, &ihid->flags);
	return ret;
}

static int i2c_hid_hwreset(struct i2c_hid *ihid)
{
	int ret;

	i2c_hid_dbg(ihid, "%s\n", __func__);

	/*
	 * This prevents sending feature reports while the device is
	 * being reset. Otherwise we may lose the reset complete
	 * interrupt.
	 */
	mutex_lock(&ihid->reset_lock);

	ret = i2c_hid_set_power(ihid, I2C_HID_PWR_ON);
	if (ret)
		goto out_unlock;

	ret = i2c_hid_execute_reset(ihid);
	if (ret) {
		dev_err(&ihid->client->dev,
			"failed to reset device: %d\n", ret);
		i2c_hid_set_power(ihid, I2C_HID_PWR_SLEEP);
		goto out_unlock;
	}

	/* At least some SIS devices need this after reset */
	if (!(ihid->quirks & I2C_HID_QUIRK_NO_WAKEUP_AFTER_RESET))
		ret = i2c_hid_set_power(ihid, I2C_HID_PWR_ON);

out_unlock:
	mutex_unlock(&ihid->reset_lock);
	return ret;

err_clear_reset:
	clear_bit(I2C_HID_RESET_PENDING, &ihid->flags);
	i2c_hid_set_power(ihid, I2C_HID_PWR_SLEEP);
err_unlock:
	mutex_unlock(&ihid->reset_lock);
	return ret;
}