Skip to content

Commit ea36bf1

Browse files
kennylevinsenJiri Kosina
authored andcommitted
HID: i2c-hid: Revert to await reset ACK before reading report descriptor
In af93a16, i2c_hid_parse was changed to continue with reading the report descriptor before waiting for reset to be acknowledged. This has lead to two regressions: 1. We fail to handle reset acknowledgment if it happens while reading the report descriptor. The transfer sets I2C_HID_READ_PENDING, which causes the IRQ handler to return without doing anything. This affects both a Wacom touchscreen and a Sensel touchpad. 2. On a Sensel touchpad, reading the report descriptor this quickly after reset results in all zeroes or partial zeroes. The issues were observed on the Lenovo Thinkpad Z16 Gen 2. The change in question was made based on a Microsoft article[0] stating that Windows 8 *may* read the report descriptor in parallel with awaiting reset acknowledgment, intended as a slight reset performance optimization. Perhaps they only do this if reset is not completing quickly enough for their tastes? As the code is not currently ready to read registers in parallel with a pending reset acknowledgment, and as reading quickly breaks the report descriptor on the Sensel touchpad, revert to waiting for reset acknowledgment before proceeding to read the report descriptor. [0]: https://learn.microsoft.com/en-us/windows-hardware/drivers/hid/plug-and-play-support-and-power-management Fixes: af93a16 ("HID: i2c-hid: Move i2c_hid_finish_hwreset() to after reading the report-descriptor") Closes: https://bugzilla.redhat.com/show_bug.cgi?id=2271136 Cc: [email protected] Signed-off-by: Kenny Levinsen <[email protected]> Link: https://lore.kernel.org/r/[email protected] [[email protected] Drop no longer necessary abort_reset error exit path] Signed-off-by: Hans de Goede <[email protected]> Tested-by: Mark Pearson <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent 8db8c77 commit ea36bf1

File tree

1 file changed

+8
-21
lines changed

1 file changed

+8
-21
lines changed

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

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -726,12 +726,15 @@ static int i2c_hid_parse(struct hid_device *hid)
726726
mutex_lock(&ihid->reset_lock);
727727
do {
728728
ret = i2c_hid_start_hwreset(ihid);
729-
if (ret)
729+
if (ret == 0)
730+
ret = i2c_hid_finish_hwreset(ihid);
731+
else
730732
msleep(1000);
731733
} while (tries-- > 0 && ret);
734+
mutex_unlock(&ihid->reset_lock);
732735

733736
if (ret)
734-
goto abort_reset;
737+
return ret;
735738

736739
use_override = i2c_hid_get_dmi_hid_report_desc_override(client->name,
737740
&rsize);
@@ -741,11 +744,8 @@ static int i2c_hid_parse(struct hid_device *hid)
741744
i2c_hid_dbg(ihid, "Using a HID report descriptor override\n");
742745
} else {
743746
rdesc = kzalloc(rsize, GFP_KERNEL);
744-
745-
if (!rdesc) {
746-
ret = -ENOMEM;
747-
goto abort_reset;
748-
}
747+
if (!rdesc)
748+
return -ENOMEM;
749749

750750
i2c_hid_dbg(ihid, "asking HID report descriptor\n");
751751

@@ -754,23 +754,10 @@ static int i2c_hid_parse(struct hid_device *hid)
754754
rdesc, rsize);
755755
if (ret) {
756756
hid_err(hid, "reading report descriptor failed\n");
757-
goto abort_reset;
757+
goto out;
758758
}
759759
}
760760

761-
/*
762-
* Windows directly reads the report-descriptor after sending reset
763-
* and then waits for resets completion afterwards. Some touchpads
764-
* actually wait for the report-descriptor to be read before signalling
765-
* reset completion.
766-
*/
767-
ret = i2c_hid_finish_hwreset(ihid);
768-
abort_reset:
769-
clear_bit(I2C_HID_RESET_PENDING, &ihid->flags);
770-
mutex_unlock(&ihid->reset_lock);
771-
if (ret)
772-
goto out;
773-
774761
i2c_hid_dbg(ihid, "Report Descriptor: %*ph\n", rsize, rdesc);
775762

776763
ret = hid_parse_report(hid, rdesc, rsize);

0 commit comments

Comments
 (0)