Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 19 Jan 2024 16:33:34 GMT
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: 60452092dbdf - stable/14 - ig4: Actively use FIFO thresholds
Message-ID:  <202401191633.40JGXYj4025937@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch stable/14 has been updated by mav:

URL: https://cgit.FreeBSD.org/src/commit/?id=60452092dbdf9c192dddd9b8d38feaa2b797c8b8

commit 60452092dbdf9c192dddd9b8d38feaa2b797c8b8
Author:     Alexander Motin <mav@FreeBSD.org>
AuthorDate: 2023-12-24 23:18:11 +0000
Commit:     Alexander Motin <mav@FreeBSD.org>
CommitDate: 2024-01-19 16:33:10 +0000

    ig4: Actively use FIFO thresholds
    
    Before every wait for FIFO interrupt set how much data/space do we
    want to see there.  Previous code was not using it for receive, as
    result aggregating interrupts only within processing latency.  The
    new code needs only one interrupt per transfer per FIFO length.
    
    On my Dell XPS 13 9310 with iichid(4) touchscreen and touchpad this
    reduces the interrupt rate per device down to 2 per sample or 16-20
    per second when idle and 120-160 per second when actively touched.
    
    MFC after:      1 month
    
    (cherry picked from commit 13037eaabede7fb7fbc25f4e84b549c73f9acb3c)
---
 sys/dev/ichiic/ig4_iic.c | 37 +++++++++++++++++--------------------
 1 file changed, 17 insertions(+), 20 deletions(-)

diff --git a/sys/dev/ichiic/ig4_iic.c b/sys/dev/ichiic/ig4_iic.c
index 3a3271454738..749a39e25117 100644
--- a/sys/dev/ichiic/ig4_iic.c
+++ b/sys/dev/ichiic/ig4_iic.c
@@ -347,6 +347,7 @@ set_slave_addr(ig4iic_softc_t *sc, uint8_t slave)
 	/*
 	 * Wait for TXFIFO to drain before disabling the controller.
 	 */
+	reg_write(sc, IG4_REG_TX_TL, 0);
 	wait_intr(sc, IG4_INTR_TX_EMPTY);
 
 	set_controller(sc, 0);
@@ -434,16 +435,20 @@ ig4iic_read(ig4iic_softc_t *sc, uint8_t *buf, uint16_t len,
 		return (0);
 
 	while (received < len) {
+		/* Ensure we have some free space in TXFIFO */
 		burst = sc->cfg.txfifo_depth -
 		    (reg_read(sc, IG4_REG_TXFLR) & IG4_FIFOLVL_MASK);
 		if (burst <= 0) {
+			reg_write(sc, IG4_REG_TX_TL, IG4_FIFO_LOWAT);
 			error = wait_intr(sc, IG4_INTR_TX_EMPTY);
 			if (error)
 				break;
-			burst = sc->cfg.txfifo_depth;
+			burst = sc->cfg.txfifo_depth -
+			    (reg_read(sc, IG4_REG_TXFLR) & IG4_FIFOLVL_MASK);
 		}
 		/* Ensure we have enough free space in RXFIFO */
-		burst = MIN(burst, sc->cfg.rxfifo_depth - lowat);
+		burst = MIN(burst, sc->cfg.rxfifo_depth -
+		    (requested - received));
 		target = MIN(requested + burst, (int)len);
 		while (requested < target) {
 			cmd = IG4_DATA_COMMAND_RD;
@@ -460,13 +465,15 @@ ig4iic_read(ig4iic_softc_t *sc, uint8_t *buf, uint16_t len,
 			lowat = IG4_FIFO_LOWAT;
 		/* After TXFLR fills up, clear it by reading available data */
 		while (received < requested - lowat) {
-			burst = MIN((int)len - received,
+			burst = MIN(requested - received,
 			    reg_read(sc, IG4_REG_RXFLR) & IG4_FIFOLVL_MASK);
 			if (burst > 0) {
 				while (burst--)
 					buf[received++] = 0xFF &
 					    reg_read(sc, IG4_REG_DATA_CMD);
 			} else {
+				reg_write(sc, IG4_REG_RX_TL,
+				    requested - received - lowat - 1);
 				error = wait_intr(sc, IG4_INTR_RX_FULL);
 				if (error)
 					goto out;
@@ -484,8 +491,7 @@ ig4iic_write(ig4iic_softc_t *sc, uint8_t *buf, uint16_t len,
 	uint32_t cmd;
 	int sent = 0;
 	int burst, target;
-	int error;
-	bool lowat_set = false;
+	int error, lowat;
 
 	if (len == 0)
 		return (0);
@@ -494,12 +500,7 @@ ig4iic_write(ig4iic_softc_t *sc, uint8_t *buf, uint16_t len,
 		burst = sc->cfg.txfifo_depth -
 		    (reg_read(sc, IG4_REG_TXFLR) & IG4_FIFOLVL_MASK);
 		target = MIN(sent + burst, (int)len);
-		/* Leave some data queued to maintain the hardware pipeline */
-		if (!lowat_set && target != len) {
-			lowat_set = true;
-			reg_write(sc, IG4_REG_TX_TL, IG4_FIFO_LOWAT);
-		}
-		while(sent < target) {
+		while (sent < target) {
 			cmd = buf[sent];
 			if (repeated_start && sent == 0)
 				cmd |= IG4_DATA_RESTART;
@@ -509,13 +510,16 @@ ig4iic_write(ig4iic_softc_t *sc, uint8_t *buf, uint16_t len,
 			sent++;
 		}
 		if (sent < len) {
+			if (len - sent <= sc->cfg.txfifo_depth)
+				lowat = sc->cfg.txfifo_depth - (len - sent);
+			else
+				lowat = IG4_FIFO_LOWAT;
+			reg_write(sc, IG4_REG_TX_TL, lowat);
 			error = wait_intr(sc, IG4_INTR_TX_EMPTY);
 			if (error)
 				break;
 		}
 	}
-	if (lowat_set)
-		reg_write(sc, IG4_REG_TX_TL, 0);
 
 	return (error);
 }
@@ -971,13 +975,6 @@ ig4iic_set_config(ig4iic_softc_t *sc, bool reset)
 	    (sc->cfg.bus_speed  & IG4_CTL_SPEED_MASK) == IG4_CTL_SPEED_STD ?
 	      sc->cfg.ss_sda_hold : sc->cfg.fs_sda_hold);
 
-	/*
-	 * Use a threshold of 1 so we get interrupted on each character,
-	 * allowing us to use mtx_sleep() in our poll code.  Not perfect
-	 * but this is better than using DELAY() for receiving data.
-	 *
-	 * See ig4_var.h for details on interrupt handler synchronization.
-	 */
 	reg_write(sc, IG4_REG_RX_TL, 0);
 	reg_write(sc, IG4_REG_TX_TL, 0);
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202401191633.40JGXYj4025937>