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