git: 094860333aaf - stable/13 - iichid(4): disable interrupt on suspend

Vladimir Kondratyev wulf at FreeBSD.org
Mon Aug 16 00:49:48 UTC 2021


The branch stable/13 has been updated by wulf:

URL: https://cgit.FreeBSD.org/src/commit/?id=094860333aaf63c922319f112601091af0c65ac9

commit 094860333aaf63c922319f112601091af0c65ac9
Author:     J.R. Oldroyd <jr at opal.com>
AuthorDate: 2021-05-31 19:33:07 +0000
Commit:     Vladimir Kondratyev <wulf at FreeBSD.org>
CommitDate: 2021-08-16 00:45:44 +0000

    iichid(4): disable interrupt on suspend
    
    Commit message of the identical change in Linux driver says:
    "When an I2C HID device is powered off during system sleep, as a result
    of removing its power resources (by the ACPI core) the interrupt line
    might go low as well.  This results inadvertent interrupts."
    
    This change fixes suspend/resume on Asus S510UQ laptops.
    
    While here add a couple of typo fixes as well as a slight change to the
    iichid_attach() code to have the power_on flag set properly.
    
    Submitted by:   J.R. Oldroyd <jr_AT_opal_DOT_com>
    Reviewed by:    wulf
    
    (cherry picked from commit 5236888db77194c194706b122675af7355fe7ceb)
---
 sys/dev/iicbus/iichid.c | 27 +++++++++++++++++++++------
 1 file changed, 21 insertions(+), 6 deletions(-)

diff --git a/sys/dev/iicbus/iichid.c b/sys/dev/iicbus/iichid.c
index 7c51a697c4c7..68d7cfd9090f 100644
--- a/sys/dev/iicbus/iichid.c
+++ b/sys/dev/iicbus/iichid.c
@@ -573,7 +573,7 @@ iichid_intr(void *context)
 	 * not allowed and often returns a garbage.  If a HOST needs to
 	 * communicate with the DEVICE it MUST issue a SET POWER command
 	 * (to ON) before any other command. As some hardware requires reads to
-	 * acknoledge interrupts we fetch only length header and discard it.
+	 * acknowledge interrupts we fetch only length header and discard it.
 	 */
 	maxlen = sc->power_on ? sc->intr_bufsize : 0;
 	error = iichid_cmd_read(sc, sc->intr_buf, maxlen, &actual);
@@ -1069,14 +1069,16 @@ iichid_attach(device_t dev)
 	error = iichid_reset(sc);
 	if (error) {
 		device_printf(dev, "failed to reset hardware: %d\n", error);
-		return (ENXIO);
+		error = ENXIO;
+		goto done;
 	}
 
-	sc->power_on = false;
+	sc->power_on = true;
+
 #ifdef IICHID_SAMPLING
 	TASK_INIT(&sc->event_task, 0, iichid_event_task, sc);
 	/* taskqueue_create can't fail with M_WAITOK mflag passed. */
-	sc->taskqueue = taskqueue_create("hmt_tq", M_WAITOK | M_ZERO,
+	sc->taskqueue = taskqueue_create("iichid_tq", M_WAITOK | M_ZERO,
 	    taskqueue_thread_enqueue, &sc->taskqueue);
 	TIMEOUT_TASK_INIT(sc->taskqueue, &sc->periodic_task, 0,
 	    iichid_event_task, sc);
@@ -1144,8 +1146,10 @@ iichid_attach(device_t dev)
 		device_printf(dev, "failed to attach child: error %d\n", error);
 		iichid_detach(dev);
 	}
+
 done:
 	(void)iichid_set_power(sc, I2C_HID_POWER_OFF);
+	sc->power_on = false;
 	return (error);
 }
 
@@ -1178,21 +1182,27 @@ iichid_suspend(device_t dev)
 	int error;
 
 	sc = device_get_softc(dev);
-	DPRINTF(sc, "Suspend called, setting device to power_state 1\n");
 	(void)bus_generic_suspend(dev);
+#ifdef IICHID_SAMPLING
+	if (sc->sampling_rate_slow < 0)
+#endif
+		(void)bus_generic_suspend_intr(device_get_parent(dev), dev,
+		    sc->irq_res);
+
 	/*
 	 * 8.2 - The HOST is going into a deep power optimized state and wishes
 	 * to put all the devices into a low power state also.  The HOST
 	 * is recommended to issue a HIPO command to the DEVICE to force
 	 * the DEVICE in to a lower power state.
 	 */
+	DPRINTF(sc, "Suspend called, setting device to power_state 1\n");
 	error = iichid_set_power_state(sc, IICHID_PS_NULL, IICHID_PS_OFF);
 	if (error != 0)
 		DPRINTF(sc, "Could not set power_state, error: %d\n", error);
 	else
 		DPRINTF(sc, "Successfully set power_state\n");
 
-        return (0);
+	return (0);
 }
 
 static int
@@ -1209,6 +1219,11 @@ iichid_resume(device_t dev)
 	else
 		DPRINTF(sc, "Successfully set power_state\n");
 	(void)bus_generic_resume(dev);
+#ifdef IICHID_SAMPLING
+	if (sc->sampling_rate_slow < 0)
+#endif
+		(void)bus_generic_resume_intr(device_get_parent(dev), dev,
+		    sc->irq_res);
 
 	return (0);
 }


More information about the dev-commits-src-all mailing list