I still haven't figured out why ihidev doesn't receive interrupts 
for I2C devices on Intel 100 series and newer.

But on an Intel 300 series laptop, I noticed that the Elan 
touchscreen (ims at ihidev) does actually generate interrupts while 
the Elan touchpad (imt at ihidev) doesn't.  In this scenario, we can 
disable polling on the touchscreen to save some power and make input 
smoother.

This diff always sets up the interrupt even when polling is 
requested, and if the interrupt handler ever fires when polling is 
enabled, disable polling.


Index: dev/acpi/dwiic_acpi.c
===================================================================
RCS file: /cvs/src/sys/dev/acpi/dwiic_acpi.c,v
retrieving revision 1.8
diff -u -p -u -p -r1.8 dwiic_acpi.c
--- dev/acpi/dwiic_acpi.c       1 Jul 2018 11:37:11 -0000       1.8
+++ dev/acpi/dwiic_acpi.c       16 Mar 2019 15:39:34 -0000
@@ -462,8 +462,9 @@ dwiic_acpi_found_ihidev(struct dwiic_sof
 
        aml_freevalue(&res);
 
-       if (!sc->sc_poll_ihidev &&
-           !(crs.irq_int == 0 && crs.gpio_int_node == NULL))
+       if (sc->sc_poll_ihidev)
+               ia.ia_poll = 1;
+       if (!(crs.irq_int == 0 && crs.gpio_int_node == NULL))
                ia.ia_intr = &crs;
 
        if (config_found(sc->sc_iic, &ia, dwiic_i2c_print)) {
Index: dev/i2c/i2cvar.h
===================================================================
RCS file: /cvs/src/sys/dev/i2c/i2cvar.h,v
retrieving revision 1.16
diff -u -p -u -p -r1.16 i2cvar.h
--- dev/i2c/i2cvar.h    23 Apr 2016 09:40:28 -0000      1.16
+++ dev/i2c/i2cvar.h    16 Mar 2019 15:39:34 -0000
@@ -113,6 +113,7 @@ struct i2c_attach_args {
        char            *ia_name;       /* chip name */
        void            *ia_cookie;     /* pass extra info from bus to dev */
        void            *ia_intr;       /* interrupt info */
+       int             ia_poll;        /* to force polling */
 };
 
 /*
Index: dev/i2c/ihidev.c
===================================================================
RCS file: /cvs/src/sys/dev/i2c/ihidev.c,v
retrieving revision 1.18
diff -u -p -u -p -r1.18 ihidev.c
--- dev/i2c/ihidev.c    20 Sep 2018 01:19:56 -0000      1.18
+++ dev/i2c/ihidev.c    16 Mar 2019 15:39:34 -0000
@@ -128,7 +128,7 @@ ihidev_attach(struct device *parent, str
                        printf(", can't establish interrupt");
        }
 
-       if (sc->sc_ih == NULL) {
+       if (ia->ia_poll) {
                printf(" (polling)");
                sc->sc_poll = 1;
                sc->sc_fastpoll = 1;
@@ -580,6 +580,16 @@ ihidev_hid_desc_parse(struct ihidev_soft
        return (0);
 }
 
+void
+ihidev_poll(void *arg)
+{
+       struct ihidev_softc *sc = arg;
+
+       sc->sc_dopoll = 1;
+       ihidev_intr(sc);
+       sc->sc_dopoll = 0;
+}
+
 int
 ihidev_intr(void *arg)
 {
@@ -590,6 +600,13 @@ ihidev_intr(void *arg)
        u_char *p;
        u_int rep = 0;
 
+       if (sc->sc_poll && !sc->sc_dopoll) {
+               printf("%s: received interrupt while polling, disabling "
+                   "polling\n", sc->sc_dev.dv_xname);
+               sc->sc_poll = 0;
+               timeout_del(&sc->sc_timer);
+       }
+
        /*
         * XXX: force I2C_F_POLL for now to avoid dwiic interrupting
         * while we are interrupting
@@ -741,7 +758,7 @@ ihidev_open(struct ihidev *scd)
 
        if (sc->sc_poll) {
                if (!timeout_initialized(&sc->sc_timer))
-                       timeout_set(&sc->sc_timer, (void *)ihidev_intr, sc);
+                       timeout_set(&sc->sc_timer, (void *)ihidev_poll, sc);
                if (!timeout_pending(&sc->sc_timer))
                        timeout_add(&sc->sc_timer, FAST_POLL_MS);
        }
Index: dev/i2c/ihidev.h
===================================================================
RCS file: /cvs/src/sys/dev/i2c/ihidev.h,v
retrieving revision 1.6
diff -u -p -u -p -r1.6 ihidev.h
--- dev/i2c/ihidev.h    25 Aug 2018 18:32:05 -0000      1.6
+++ dev/i2c/ihidev.h    16 Mar 2019 15:39:34 -0000
@@ -89,6 +89,7 @@ struct ihidev_softc {
        int             sc_refcnt;
 
        int             sc_poll;
+       int             sc_dopoll;
        int             sc_fastpoll;
        struct timeout  sc_timer;
 };

Reply via email to