The branch main has been updated by avg:

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

commit a4fe8922085dfc1e5e6a6bac73ccc738e373165f
Author:     Andriy Gapon <a...@freebsd.org>
AuthorDate: 2021-11-26 07:44:30 +0000
Commit:     Andriy Gapon <a...@freebsd.org>
CommitDate: 2021-11-26 14:16:21 +0000

    twsi: unify error handling, explicitly handle more conditions
    
    twsi_error() is a new function that stops the current transfer and sets
    up softc when an error condition is detected.
    TWSI_STATUS_DATA_WR_NACK, TWSI_STATUS_BUS_ERROR and
    TWSI_STATUS_ARBITRATION_LOST are now handled explicitly rather than
    via the catch-all unknown status.
    
    Also, twsi_intr() now calls wakeup() in a single place when the
    transfer is finished.
    
    MFC after:      2 weeks
---
 sys/dev/iicbus/twsi/twsi.c | 46 ++++++++++++++++++++++++++++++++--------------
 1 file changed, 32 insertions(+), 14 deletions(-)

diff --git a/sys/dev/iicbus/twsi/twsi.c b/sys/dev/iicbus/twsi/twsi.c
index 384e19e120b9..ecadfade04d9 100644
--- a/sys/dev/iicbus/twsi/twsi.c
+++ b/sys/dev/iicbus/twsi/twsi.c
@@ -543,6 +543,19 @@ twsi_transfer(device_t dev, struct iic_msg *msgs, uint32_t 
nmsgs)
        return (error);
 }
 
+static void
+twsi_error(struct twsi_softc *sc, int err)
+{
+       /*
+        * Must send stop condition to abort the current transfer.
+        */
+       debugf(sc, "Sending STOP condition for error %d\n", err);
+       sc->transfer = 0;
+       sc->error = err;
+       sc->control_val = 0;
+       TWSI_WRITE(sc, sc->reg_control, sc->control_val | TWSI_CONTROL_STOP);
+}
+
 static void
 twsi_intr(void *arg)
 {
@@ -604,13 +617,13 @@ twsi_intr(void *arg)
 
        case TWSI_STATUS_ADDR_W_NACK:
        case TWSI_STATUS_ADDR_R_NACK:
-               debugf(sc, "No ack received after transmitting the address\n");
-               sc->transfer = 0;
-               sc->error = IIC_ENOACK;
-               sc->control_val = 0;
-               wakeup(sc);
+               debugf(sc, "Address NACK-ed\n");
+               twsi_error(sc, IIC_ENOACK);
+               break;
+       case TWSI_STATUS_DATA_WR_NACK:
+               debugf(sc, "Data byte NACK-ed\n");
+               twsi_error(sc, IIC_ENOACK);
                break;
-
        case TWSI_STATUS_DATA_WR_ACK:
                debugf(sc, "Ack received after transmitting data\n");
                if (sc->sent_bytes == sc->msgs[sc->msg_idx].len) {
@@ -684,12 +697,17 @@ twsi_intr(void *arg)
                sc->error = 0;
                break;
 
+       case TWSI_STATUS_BUS_ERROR:
+               debugf(sc, "Bus error\n");
+               twsi_error(sc, IIC_EBUSERR);
+               break;
+       case TWSI_STATUS_ARBITRATION_LOST:
+               debugf(sc, "Arbitration lost\n");
+               twsi_error(sc, IIC_EBUSBSY);
+               break;
        default:
-               debugf(sc, "status=%x hot handled\n", status);
-               sc->transfer = 0;
-               sc->error = IIC_EBUSERR;
-               sc->control_val = 0;
-               wakeup(sc);
+               debugf(sc, "unexpected status 0x%x\n", status);
+               twsi_error(sc, IIC_ESTATUS);
                break;
        }
        debugf(sc, "Refresh reg_control\n");
@@ -701,11 +719,11 @@ end:
        TWSI_WRITE(sc, sc->reg_control, sc->control_val |
            (sc->iflag_w1c ? TWSI_CONTROL_IFLG : 0));
 
-       debugf(sc, "Done with interrupts\n\n");
-       if (transfer_done == 1) {
+       if (transfer_done == 1)
                sc->transfer = 0;
+       debugf(sc, "Done with interrupt, transfer = %d\n", sc->transfer);
+       if (sc->transfer == 0)
                wakeup(sc);
-       }
        mtx_unlock(&sc->mutex);
 }
 

Reply via email to