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: Douglas Anderson <dianders@xxxxxxxxxxxx> Signed-off-by: Hans de Goede <hdegoede@xxxxxxxxxx> --- Changes in v3: - Use "else if" to only wait for reset timeout when the I2C_HID_QUIRK_NO_IRQ_AFTER_RESET quirk is not set Changes in v2: - Move the i2c_hid_dbg(... "%s: waiting...\n" ...) to above the msleep(100) for the I2C_HID_QUIRK_NO_IRQ_AFTER_RESET quirk --- drivers/hid/i2c-hid/i2c-hid-core.c | 79 +++++++++++++----------------- 1 file changed, 33 insertions(+), 46 deletions(-) diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c index 2735cd585af0..ca2a4ccb9abf 100644 --- a/drivers/hid/i2c-hid/i2c-hid-core.c +++ b/drivers/hid/i2c-hid/i2c-hid-core.c @@ -426,49 +426,9 @@ 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) -{ - size_t length = 0; - int ret; - - i2c_hid_dbg(ihid, "resetting...\n"); - - /* Prepare reset command. Command register goes first. */ - *(__le16 *)ihid->cmdbuf = ihid->hdesc.wCommandRegister; - length += sizeof(__le16); - /* Next is RESET command itself */ - length += i2c_hid_encode_command(ihid->cmdbuf + length, - I2C_HID_OPCODE_RESET, 0, 0); - - set_bit(I2C_HID_RESET_PENDING, &ihid->flags); - - ret = i2c_hid_xfer(ihid, ihid->cmdbuf, length, NULL, 0); - if (ret) { - dev_err(&ihid->client->dev, "failed to reset device.\n"); - goto out; - } - - 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, - !test_bit(I2C_HID_RESET_PENDING, &ihid->flags), - msecs_to_jiffies(5000))) { - ret = -ENODATA; - goto out; - } - 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) { + size_t length = 0; int ret; i2c_hid_dbg(ihid, "%s\n", __func__); @@ -482,21 +442,48 @@ static int i2c_hid_hwreset(struct i2c_hid *ihid) ret = i2c_hid_set_power(ihid, I2C_HID_PWR_ON); if (ret) - goto out_unlock; + goto err_unlock; - ret = i2c_hid_execute_reset(ihid); + /* Prepare reset command. Command register goes first. */ + *(__le16 *)ihid->cmdbuf = ihid->hdesc.wCommandRegister; + length += sizeof(__le16); + /* Next is RESET command itself */ + length += i2c_hid_encode_command(ihid->cmdbuf + length, + I2C_HID_OPCODE_RESET, 0, 0); + + set_bit(I2C_HID_RESET_PENDING, &ihid->flags); + + ret = i2c_hid_xfer(ihid, ihid->cmdbuf, length, NULL, 0); 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; + goto err_clear_reset; } + i2c_hid_dbg(ihid, "%s: waiting...\n", __func__); + + if (ihid->quirks & I2C_HID_QUIRK_NO_IRQ_AFTER_RESET) { + msleep(100); + 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 err_clear_reset; + } + i2c_hid_dbg(ihid, "%s: finished.\n", __func__); + /* 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; } -- 2.41.0