Skip to content

Commit 96d3098

Browse files
jwrdegoedeJiri Kosina
authored andcommitted
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: Douglas Anderson <[email protected]> Signed-off-by: Hans de Goede <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent f023605 commit 96d3098

File tree

1 file changed

+28
-10
lines changed

1 file changed

+28
-10
lines changed

drivers/hid/i2c-hid/i2c-hid-core.c

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ static int i2c_hid_set_power(struct i2c_hid *ihid, int power_state)
426426
return ret;
427427
}
428428

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

443443
ret = i2c_hid_set_power(ihid, I2C_HID_PWR_ON);
444444
if (ret)
445-
goto err_unlock;
445+
return ret;
446446

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

463+
return 0;
464+
465+
err_clear_reset:
466+
clear_bit(I2C_HID_RESET_PENDING, &ihid->flags);
467+
i2c_hid_set_power(ihid, I2C_HID_PWR_SLEEP);
468+
return ret;
469+
}
470+
471+
static int i2c_hid_finish_hwreset(struct i2c_hid *ihid)
472+
{
473+
int ret = 0;
474+
463475
i2c_hid_dbg(ihid, "%s: waiting...\n", __func__);
464476

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

480-
mutex_unlock(&ihid->reset_lock);
481492
return ret;
482493

483494
err_clear_reset:
484495
clear_bit(I2C_HID_RESET_PENDING, &ihid->flags);
485496
i2c_hid_set_power(ihid, I2C_HID_PWR_SLEEP);
486-
err_unlock:
487-
mutex_unlock(&ihid->reset_lock);
488497
return ret;
489498
}
490499

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

733742
do {
734-
ret = i2c_hid_hwreset(ihid);
743+
mutex_lock(&ihid->reset_lock);
744+
ret = i2c_hid_start_hwreset(ihid);
745+
if (ret == 0)
746+
ret = i2c_hid_finish_hwreset(ihid);
747+
mutex_unlock(&ihid->reset_lock);
735748
if (ret)
736749
msleep(1000);
737750
} while (tries-- > 0 && ret);
@@ -974,10 +987,15 @@ static int i2c_hid_core_resume(struct i2c_hid *ihid)
974987
* However some ALPS touchpads generate IRQ storm without reset, so
975988
* let's still reset them here.
976989
*/
977-
if (ihid->quirks & I2C_HID_QUIRK_RESET_ON_RESUME)
978-
ret = i2c_hid_hwreset(ihid);
979-
else
990+
if (ihid->quirks & I2C_HID_QUIRK_RESET_ON_RESUME) {
991+
mutex_lock(&ihid->reset_lock);
992+
ret = i2c_hid_start_hwreset(ihid);
993+
if (ret == 0)
994+
ret = i2c_hid_finish_hwreset(ihid);
995+
mutex_unlock(&ihid->reset_lock);
996+
} else {
980997
ret = i2c_hid_set_power(ihid, I2C_HID_PWR_ON);
998+
}
981999

9821000
if (ret)
9831001
return ret;

0 commit comments

Comments
 (0)