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

HID: i2c-hid: Split i2c_hid_hwreset() in start() and finish() functions



Split i2c_hid_hwreset() into:

i2c_hid_start_hwreset() which sends the PWR_ON and reset commands; and
i2c_hid_finish_hwreset() which actually waits for the reset to complete.

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 f023605d
Loading
Loading
Loading
Loading
+28 −10
Original line number Diff line number Diff line
@@ -426,7 +426,7 @@ static int i2c_hid_set_power(struct i2c_hid *ihid, int power_state)
	return ret;
}

static int i2c_hid_hwreset(struct i2c_hid *ihid)
static int i2c_hid_start_hwreset(struct i2c_hid *ihid)
{
	size_t length = 0;
	int ret;
@@ -438,11 +438,11 @@ static int i2c_hid_hwreset(struct i2c_hid *ihid)
	 * being reset. Otherwise we may lose the reset complete
	 * interrupt.
	 */
	mutex_lock(&ihid->reset_lock);
	lockdep_assert_held(&ihid->reset_lock);

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

	/* Prepare reset command. Command register goes first. */
	*(__le16 *)ihid->cmdbuf = ihid->hdesc.wCommandRegister;
@@ -460,6 +460,18 @@ static int i2c_hid_hwreset(struct i2c_hid *ihid)
		goto err_clear_reset;
	}

	return 0;

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

static int i2c_hid_finish_hwreset(struct i2c_hid *ihid)
{
	int ret = 0;

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

	if (ihid->quirks & I2C_HID_QUIRK_NO_IRQ_AFTER_RESET) {
@@ -477,14 +489,11 @@ static int i2c_hid_hwreset(struct i2c_hid *ihid)
	if (!(ihid->quirks & I2C_HID_QUIRK_NO_WAKEUP_AFTER_RESET))
		ret = i2c_hid_set_power(ihid, I2C_HID_PWR_ON);

	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;
}

@@ -731,7 +740,11 @@ static int i2c_hid_parse(struct hid_device *hid)
	}

	do {
		ret = i2c_hid_hwreset(ihid);
		mutex_lock(&ihid->reset_lock);
		ret = i2c_hid_start_hwreset(ihid);
		if (ret == 0)
			ret = i2c_hid_finish_hwreset(ihid);
		mutex_unlock(&ihid->reset_lock);
		if (ret)
			msleep(1000);
	} while (tries-- > 0 && ret);
@@ -974,10 +987,15 @@ static int i2c_hid_core_resume(struct i2c_hid *ihid)
	 * However some ALPS touchpads generate IRQ storm without reset, so
	 * let's still reset them here.
	 */
	if (ihid->quirks & I2C_HID_QUIRK_RESET_ON_RESUME)
		ret = i2c_hid_hwreset(ihid);
	else
	if (ihid->quirks & I2C_HID_QUIRK_RESET_ON_RESUME) {
		mutex_lock(&ihid->reset_lock);
		ret = i2c_hid_start_hwreset(ihid);
		if (ret == 0)
			ret = i2c_hid_finish_hwreset(ihid);
		mutex_unlock(&ihid->reset_lock);
	} else {
		ret = i2c_hid_set_power(ihid, I2C_HID_PWR_ON);
	}

	if (ret)
		return ret;