[v2] HID: i2c-hid: Ignore input report if there's no data present on Elan touchpanels
diff mbox series

Message ID 20190107062656.3065-1-kai.heng.feng@canonical.com
State Superseded
Delegated to: Jiri Kosina
Headers show
Series
  • [v2] HID: i2c-hid: Ignore input report if there's no data present on Elan touchpanels
Related show

Commit Message

Kai-Heng Feng Jan. 7, 2019, 6:26 a.m. UTC
While using Elan touchpads, the message floods:
[  136.138487] i2c_hid i2c-DELL08D6:00: i2c_hid_get_input: incomplete report (14/65535)

Though the message flood is annoying, the device it self works without
any issue. I suspect that the device in question takes too much time to
pull the IRQ back to high after I2C host has done reading its data.

Since the host receives all useful data, let's ignore the input report
when there's no data.

Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
---
v2:
 Use dev_warn_once() to warn the user about the situation.

 drivers/hid/i2c-hid/i2c-hid-core.c | 9 +++++++++
 1 file changed, 9 insertions(+)

Comments

kbuild test robot Jan. 7, 2019, 7:31 a.m. UTC | #1
Hi Kai-Heng,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on linus/master]
[also build test ERROR on v5.0-rc1]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Kai-Heng-Feng/HID-i2c-hid-Ignore-input-report-if-there-s-no-data-present-on-Elan-touchpanels/20190107-142834
config: xtensa-allmodconfig (attached as .config)
compiler: xtensa-linux-gcc (GCC) 8.1.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=8.1.0 make.cross ARCH=xtensa 

All errors (new ones prefixed by >>):

   drivers/hid/i2c-hid/i2c-hid-core.c: In function 'i2c_hid_get_input':
   drivers/hid/i2c-hid/i2c-hid-core.c:510:37: warning: missing terminating " character
      dev_warn_once(&ihid->client->dev, "%s: IRQ triggered but
                                        ^
   drivers/hid/i2c-hid/i2c-hid-core.c:511:15: warning: missing terminating ' character
             there's no data\n", __func__);
                  ^
   drivers/hid/i2c-hid/i2c-hid-core.c:1359: error: unterminated argument list invoking macro "dev_warn_once"
    MODULE_LICENSE("GPL");
    
>> drivers/hid/i2c-hid/i2c-hid-core.c:510:3: error: 'dev_warn_once' undeclared (first use in this function); did you mean 'dev_fwnode'?
      dev_warn_once(&ihid->client->dev, "%s: IRQ triggered but
      ^~~~~~~~~~~~~
      dev_fwnode
   drivers/hid/i2c-hid/i2c-hid-core.c:510:3: note: each undeclared identifier is reported only once for each function it appears in
   drivers/hid/i2c-hid/i2c-hid-core.c:510:16: error: expected ';' at end of input
      dev_warn_once(&ihid->client->dev, "%s: IRQ triggered but
                   ^
                   ;
   drivers/hid/i2c-hid/i2c-hid-core.c:1359:
    MODULE_LICENSE("GPL");
                    
   drivers/hid/i2c-hid/i2c-hid-core.c:510:3: error: expected declaration or statement at end of input
      dev_warn_once(&ihid->client->dev, "%s: IRQ triggered but
      ^~~~~~~~~~~~~
   drivers/hid/i2c-hid/i2c-hid-core.c:510:3: error: expected declaration or statement at end of input
   At top level:
   drivers/hid/i2c-hid/i2c-hid-core.c:481:13: warning: 'i2c_hid_get_input' defined but not used [-Wunused-function]
    static void i2c_hid_get_input(struct i2c_hid *ihid)
                ^~~~~~~~~~~~~~~~~
   drivers/hid/i2c-hid/i2c-hid-core.c:441:12: warning: 'i2c_hid_hwreset' defined but not used [-Wunused-function]
    static int i2c_hid_hwreset(struct i2c_client *client)
               ^~~~~~~~~~~~~~~
   drivers/hid/i2c-hid/i2c-hid-core.c:330:12: warning: 'i2c_hid_set_or_send_report' defined but not used [-Wunused-function]
    static int i2c_hid_set_or_send_report(struct i2c_client *client, u8 reportType,
               ^~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/hid/i2c-hid/i2c-hid-core.c:291:12: warning: 'i2c_hid_get_report' defined but not used [-Wunused-function]
    static int i2c_hid_get_report(struct i2c_client *client, u8 reportType,
               ^~~~~~~~~~~~~~~~~~
   drivers/hid/i2c-hid/i2c-hid-core.c:195:12: warning: 'i2c_hid_lookup_quirk' defined but not used [-Wunused-function]
    static u32 i2c_hid_lookup_quirk(const u16 idVendor, const u16 idProduct)
               ^~~~~~~~~~~~~~~~~~~~

vim +510 drivers/hid/i2c-hid/i2c-hid-core.c

   480	
   481	static void i2c_hid_get_input(struct i2c_hid *ihid)
   482	{
   483		int ret;
   484		u32 ret_size;
   485		int size = le16_to_cpu(ihid->hdesc.wMaxInputLength);
   486	
   487		if (size > ihid->bufsize)
   488			size = ihid->bufsize;
   489	
   490		ret = i2c_master_recv(ihid->client, ihid->inbuf, size);
   491		if (ret != size) {
   492			if (ret < 0)
   493				return;
   494	
   495			dev_err(&ihid->client->dev, "%s: got %d data instead of %d\n",
   496				__func__, ret, size);
   497			return;
   498		}
   499	
   500		ret_size = ihid->inbuf[0] | ihid->inbuf[1] << 8;
   501	
   502		if (!ret_size) {
   503			/* host or device initiated RESET completed */
   504			if (test_and_clear_bit(I2C_HID_RESET_PENDING, &ihid->flags))
   505				wake_up(&ihid->wait);
   506			return;
   507		}
   508	
   509		if (ihid->quirks & I2C_HID_QUIRK_BOGUS_IRQ && ret_size == 0xffff) {
 > 510			dev_warn_once(&ihid->client->dev, "%s: IRQ triggered but
   511				      there's no data\n", __func__);
   512			return;
   513		}
   514	
   515		if ((ret_size > size) || (ret_size < 2)) {
   516			dev_err(&ihid->client->dev, "%s: incomplete report (%d/%d)\n",
   517				__func__, size, ret_size);
   518			return;
   519		}
   520	
   521		i2c_hid_dbg(ihid, "input: %*ph\n", ret_size, ihid->inbuf);
   522	
   523		if (test_bit(I2C_HID_STARTED, &ihid->flags))
   524			hid_input_report(ihid->hid, HID_INPUT_REPORT, ihid->inbuf + 2,
   525					ret_size - 2, 1);
   526	
   527		return;
   528	}
   529	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

Patch
diff mbox series

diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c
index 8555ce7e737b..fd3b0ddace27 100644
--- a/drivers/hid/i2c-hid/i2c-hid-core.c
+++ b/drivers/hid/i2c-hid/i2c-hid-core.c
@@ -50,6 +50,7 @@ 
 #define I2C_HID_QUIRK_NO_IRQ_AFTER_RESET	BIT(1)
 #define I2C_HID_QUIRK_NO_RUNTIME_PM		BIT(2)
 #define I2C_HID_QUIRK_DELAY_AFTER_SLEEP		BIT(3)
+#define I2C_HID_QUIRK_BOGUS_IRQ			BIT(4)
 
 /* flags */
 #define I2C_HID_STARTED		0
@@ -179,6 +180,8 @@  static const struct i2c_hid_quirks {
 		I2C_HID_QUIRK_DELAY_AFTER_SLEEP },
 	{ USB_VENDOR_ID_LG, I2C_DEVICE_ID_LG_8001,
 		I2C_HID_QUIRK_NO_RUNTIME_PM },
+	{ USB_VENDOR_ID_ELAN, HID_ANY_ID,
+		 I2C_HID_QUIRK_BOGUS_IRQ },
 	{ 0, 0 }
 };
 
@@ -503,6 +506,12 @@  static void i2c_hid_get_input(struct i2c_hid *ihid)
 		return;
 	}
 
+	if (ihid->quirks & I2C_HID_QUIRK_BOGUS_IRQ && ret_size == 0xffff) {
+		dev_warn_once(&ihid->client->dev, "%s: IRQ triggered but
+			      there's no data\n", __func__);
+		return;
+	}
+
 	if ((ret_size > size) || (ret_size < 2)) {
 		dev_err(&ihid->client->dev, "%s: incomplete report (%d/%d)\n",
 			__func__, size, ret_size);