diff mbox series

HID: i2c-hid: enforce I2C_HID_QUIRK_RESEND_REPORT_DESCR

Message ID 20180831095417.8541-1-benjamin.tissoires@redhat.com (mailing list archive)
State New, archived
Headers show
Series HID: i2c-hid: enforce I2C_HID_QUIRK_RESEND_REPORT_DESCR | expand

Commit Message

Benjamin Tissoires Aug. 31, 2018, 9:54 a.m. UTC
The spec states that the HID devices should allow
the host to query the HID descriptor at any time.

Some devices require the HID descriptor to be set
on resume, or they will fail.

Instead of having a growing list of blacklisted devices
make the call part of the general resume process
so we can remove this list.

Tested on a Dell XPS 9360 and a Surface 3.

link: https://bugzilla.redhat.com/show_bug.cgi?id=1622695

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---
 drivers/hid/i2c-hid/i2c-hid.c | 16 ++++------------
 1 file changed, 4 insertions(+), 12 deletions(-)

Comments

Hans de Goede Aug. 31, 2018, 10:04 a.m. UTC | #1
Hi,

On 31-08-18 11:54, Benjamin Tissoires wrote:
> The spec states that the HID devices should allow
> the host to query the HID descriptor at any time.
> 
> Some devices require the HID descriptor to be set
> on resume, or they will fail.
> 
> Instead of having a growing list of blacklisted devices
> make the call part of the general resume process
> so we can remove this list.
> 
> Tested on a Dell XPS 9360 and a Surface 3.
> 
> link: https://bugzilla.redhat.com/show_bug.cgi?id=1622695
> 
> Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>

I agree we should just do this everywhere:

Acked-by: Hans de Goede <hdegoede@redhat.com>

Regards,

Hans

> ---
>   drivers/hid/i2c-hid/i2c-hid.c | 16 ++++------------
>   1 file changed, 4 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
> index 57126f6837bb..17ec57c62a0b 100644
> --- a/drivers/hid/i2c-hid/i2c-hid.c
> +++ b/drivers/hid/i2c-hid/i2c-hid.c
> @@ -47,7 +47,7 @@
>   /* quirks to control the device */
>   #define I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV	BIT(0)
>   #define I2C_HID_QUIRK_NO_IRQ_AFTER_RESET	BIT(1)
> -#define I2C_HID_QUIRK_RESEND_REPORT_DESCR	BIT(2)
> +/* reserved: I2C_HID_QUIRK_RESEND_REPORT_DESCR	BIT(2) */
>   
>   /* flags */
>   #define I2C_HID_STARTED		0
> @@ -170,12 +170,6 @@ static const struct i2c_hid_quirks {
>   		I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV },
>   	{ I2C_VENDOR_ID_HANTICK, I2C_PRODUCT_ID_HANTICK_5288,
>   		I2C_HID_QUIRK_NO_IRQ_AFTER_RESET },
> -	{ I2C_VENDOR_ID_RAYD, I2C_PRODUCT_ID_RAYD_3118,
> -		I2C_HID_QUIRK_RESEND_REPORT_DESCR },
> -	{ USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS10FB_TOUCH,
> -		I2C_HID_QUIRK_RESEND_REPORT_DESCR },
> -	{ I2C_VENDOR_ID_RAYD, I2C_PRODUCT_ID_RAYD_4B33,
> -		I2C_HID_QUIRK_RESEND_REPORT_DESCR },
>   	{ 0, 0 }
>   };
>   
> @@ -1245,11 +1239,9 @@ static int i2c_hid_resume(struct device *dev)
>   	 * after resume, after this it will be back normal.
>   	 * otherwise it issues too many incomplete reports.
>   	 */
> -	if (ihid->quirks & I2C_HID_QUIRK_RESEND_REPORT_DESCR) {
> -		ret = i2c_hid_command(client, &hid_report_descr_cmd, NULL, 0);
> -		if (ret)
> -			return ret;
> -	}
> +	ret = i2c_hid_command(client, &hid_report_descr_cmd, NULL, 0);
> +	if (ret)
> +		return ret;
>   
>   	if (hid->driver && hid->driver->reset_resume) {
>   		ret = hid->driver->reset_resume(hid);
>
Benjamin Tissoires Sept. 3, 2018, 9:41 a.m. UTC | #2
On Fri, Aug 31, 2018 at 12:04 PM Hans de Goede <hdegoede@redhat.com> wrote:
>
> Hi,
>
> On 31-08-18 11:54, Benjamin Tissoires wrote:
> > The spec states that the HID devices should allow
> > the host to query the HID descriptor at any time.
> >
> > Some devices require the HID descriptor to be set
> > on resume, or they will fail.
> >
> > Instead of having a growing list of blacklisted devices
> > make the call part of the general resume process
> > so we can remove this list.
> >
> > Tested on a Dell XPS 9360 and a Surface 3.
> >
> > link: https://bugzilla.redhat.com/show_bug.cgi?id=1622695
> >
> > Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
>
> I agree we should just do this everywhere:
>
> Acked-by: Hans de Goede <hdegoede@redhat.com>

Jiri, please hold with this patch, Canonical might have found a better
solution. Simply not resetting the device after S3 might be the trick.

Cheers,
Benjamin

>
> Regards,
>
> Hans
>
> > ---
> >   drivers/hid/i2c-hid/i2c-hid.c | 16 ++++------------
> >   1 file changed, 4 insertions(+), 12 deletions(-)
> >
> > diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
> > index 57126f6837bb..17ec57c62a0b 100644
> > --- a/drivers/hid/i2c-hid/i2c-hid.c
> > +++ b/drivers/hid/i2c-hid/i2c-hid.c
> > @@ -47,7 +47,7 @@
> >   /* quirks to control the device */
> >   #define I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV    BIT(0)
> >   #define I2C_HID_QUIRK_NO_IRQ_AFTER_RESET    BIT(1)
> > -#define I2C_HID_QUIRK_RESEND_REPORT_DESCR    BIT(2)
> > +/* reserved: I2C_HID_QUIRK_RESEND_REPORT_DESCR       BIT(2) */
> >
> >   /* flags */
> >   #define I2C_HID_STARTED             0
> > @@ -170,12 +170,6 @@ static const struct i2c_hid_quirks {
> >               I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV },
> >       { I2C_VENDOR_ID_HANTICK, I2C_PRODUCT_ID_HANTICK_5288,
> >               I2C_HID_QUIRK_NO_IRQ_AFTER_RESET },
> > -     { I2C_VENDOR_ID_RAYD, I2C_PRODUCT_ID_RAYD_3118,
> > -             I2C_HID_QUIRK_RESEND_REPORT_DESCR },
> > -     { USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS10FB_TOUCH,
> > -             I2C_HID_QUIRK_RESEND_REPORT_DESCR },
> > -     { I2C_VENDOR_ID_RAYD, I2C_PRODUCT_ID_RAYD_4B33,
> > -             I2C_HID_QUIRK_RESEND_REPORT_DESCR },
> >       { 0, 0 }
> >   };
> >
> > @@ -1245,11 +1239,9 @@ static int i2c_hid_resume(struct device *dev)
> >        * after resume, after this it will be back normal.
> >        * otherwise it issues too many incomplete reports.
> >        */
> > -     if (ihid->quirks & I2C_HID_QUIRK_RESEND_REPORT_DESCR) {
> > -             ret = i2c_hid_command(client, &hid_report_descr_cmd, NULL, 0);
> > -             if (ret)
> > -                     return ret;
> > -     }
> > +     ret = i2c_hid_command(client, &hid_report_descr_cmd, NULL, 0);
> > +     if (ret)
> > +             return ret;
> >
> >       if (hid->driver && hid->driver->reset_resume) {
> >               ret = hid->driver->reset_resume(hid);
> >
Jiri Kosina Sept. 3, 2018, 1:13 p.m. UTC | #3
On Mon, 3 Sep 2018, Benjamin Tissoires wrote:

> > > The spec states that the HID devices should allow
> > > the host to query the HID descriptor at any time.
> > >
> > > Some devices require the HID descriptor to be set
> > > on resume, or they will fail.
> > >
> > > Instead of having a growing list of blacklisted devices
> > > make the call part of the general resume process
> > > so we can remove this list.
> > >
> > > Tested on a Dell XPS 9360 and a Surface 3.
> > >
> > > link: https://bugzilla.redhat.com/show_bug.cgi?id=1622695
> > >
> > > Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
> >
> > I agree we should just do this everywhere:
> >
> > Acked-by: Hans de Goede <hdegoede@redhat.com>
> 
> Jiri, please hold with this patch, Canonical might have found a better
> solution. Simply not resetting the device after S3 might be the trick.

Thanks for the heads up.

In case that's the case, please also send a reference to the subsititute 
patch submission into this thread, so that archives to pick it up :)

Thanks,
Kai-Heng Feng Sept. 3, 2018, 3:54 p.m. UTC | #4
Hi Benjamin,

I forgot to include mailing list, first time -in-reply-to user :)

at 17:39, Benjamin Tissoires <benjamin.tissoires@redhat.com> wrote:

> On Mon, Sep 3, 2018 at 11:09 AM Kai-Heng Feng
> <kai.heng.feng@canonical.com> wrote:
>> Raydium touchscreen triggers interrupt storm after system-wide suspend:
>> [ 179.085033] i2c_hid i2c-CUST0000:00: i2c_hid_get_input: incomplete
>> report (58/65535)
>>
>> According to Raydium, Windows driver does not reset the device after
>> system resume.
>>
>> The HID over I2C spec does specify a reset should be used at
>> intialization, but it doesn't specify if reset is required for system
>> suspend.
>
> Hmm, that would explain a lot, thanks for digging into this.
>
> Jiri, I think this patch should partially replace
> https://patchwork.kernel.org/patch/10583481/
>
> Kai-heng, if you do not need to re-request the HID descriptors, I
> think it should be good to squash these together to:
> - remove I2C_HID_QUIRK_RESEND_REPORT_DESCR
> - remove the re-request the HID descriptors on resume
> - merge with this patch

There's still one user uses I2C_HID_QUIRK_RESEND_REPORT_DESCR,  
USB_DEVICE_ID_SIS10FB_TOUCH.
So I'd like to have an Ack from Hans first.

I'll send a new patch with your suggestion afterward.

>
>
>
>> Tested this patch on other i2c-hid touchpanels I have and those
>> touchpanels do work after S3 without doing reset. If any regression
>> happens to other touchpanel vendors, we can use quirk for Raydium
>> devices.
>>
>> Cc: AceLan Kao <acelan.kao@canonical.com>
>> Cc: Aaron Ma <aaron.ma@canonical.com>
>> Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
>> ---
>>
>> Benjamin, Hans,
>>
>> I guess some vendors interpret spec this way, so hardware reset is an
>> unexpected request for their devices.
>> Can you give this patch a try?
>
> The only device I have that you should not is the Surface 3. And I am
> not so sure it goes into S3 fluently (it seems to, but I am not 100%
> sure). If you have tested on a Dell XPS 9360, I think there is not
> much more I could test.

At least for the Raydium touchscreen, the issue can be observed under both  
S2Idle and S3.
So I guess Surface 3 is still suitable for test if it can do S2Idle.

I've test this on XPS 9370 and Precision 5520, the patch doesn't break them.

Kai-Heng

>
> Cheers,
> Benjamin
>
>>  drivers/hid/i2c-hid/i2c-hid.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
>> index 57126f6837bb..7567034a009f 100644
>> --- a/drivers/hid/i2c-hid/i2c-hid.c
>> +++ b/drivers/hid/i2c-hid/i2c-hid.c
>> @@ -1237,7 +1237,7 @@ static int i2c_hid_resume(struct device *dev)
>>         pm_runtime_enable(dev);
>>
>>         enable_irq(client->irq);
>> -       ret = i2c_hid_hwreset(client);
>> +       ret = i2c_hid_set_power(client, I2C_HID_PWR_ON);
>>         if (ret)
>>                 return ret;
>>
>> --
>> 2.17.1
diff mbox series

Patch

diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
index 57126f6837bb..17ec57c62a0b 100644
--- a/drivers/hid/i2c-hid/i2c-hid.c
+++ b/drivers/hid/i2c-hid/i2c-hid.c
@@ -47,7 +47,7 @@ 
 /* quirks to control the device */
 #define I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV	BIT(0)
 #define I2C_HID_QUIRK_NO_IRQ_AFTER_RESET	BIT(1)
-#define I2C_HID_QUIRK_RESEND_REPORT_DESCR	BIT(2)
+/* reserved: I2C_HID_QUIRK_RESEND_REPORT_DESCR	BIT(2) */
 
 /* flags */
 #define I2C_HID_STARTED		0
@@ -170,12 +170,6 @@  static const struct i2c_hid_quirks {
 		I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV },
 	{ I2C_VENDOR_ID_HANTICK, I2C_PRODUCT_ID_HANTICK_5288,
 		I2C_HID_QUIRK_NO_IRQ_AFTER_RESET },
-	{ I2C_VENDOR_ID_RAYD, I2C_PRODUCT_ID_RAYD_3118,
-		I2C_HID_QUIRK_RESEND_REPORT_DESCR },
-	{ USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS10FB_TOUCH,
-		I2C_HID_QUIRK_RESEND_REPORT_DESCR },
-	{ I2C_VENDOR_ID_RAYD, I2C_PRODUCT_ID_RAYD_4B33,
-		I2C_HID_QUIRK_RESEND_REPORT_DESCR },
 	{ 0, 0 }
 };
 
@@ -1245,11 +1239,9 @@  static int i2c_hid_resume(struct device *dev)
 	 * after resume, after this it will be back normal.
 	 * otherwise it issues too many incomplete reports.
 	 */
-	if (ihid->quirks & I2C_HID_QUIRK_RESEND_REPORT_DESCR) {
-		ret = i2c_hid_command(client, &hid_report_descr_cmd, NULL, 0);
-		if (ret)
-			return ret;
-	}
+	ret = i2c_hid_command(client, &hid_report_descr_cmd, NULL, 0);
+	if (ret)
+		return ret;
 
 	if (hid->driver && hid->driver->reset_resume) {
 		ret = hid->driver->reset_resume(hid);