Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/i2c Many I2C drivers hold spin locks between iic_acq...



details:   https://anonhg.NetBSD.org/src/rev/b1691180578d
branches:  trunk
changeset: 808254:b1691180578d
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Sun May 10 22:54:06 2015 +0000

description:
Many I2C drivers hold spin locks between iic_acquire_bus / iic_release_bus.
Avoid sleeping while owning the I2C bus.

diffstat:

 sys/dev/i2c/at24cxx.c |  35 +++++++++++++++++++++--------------
 1 files changed, 21 insertions(+), 14 deletions(-)

diffs (113 lines):

diff -r 2cd0dd0b5d93 -r b1691180578d sys/dev/i2c/at24cxx.c
--- a/sys/dev/i2c/at24cxx.c     Sun May 10 22:21:38 2015 +0000
+++ b/sys/dev/i2c/at24cxx.c     Sun May 10 22:54:06 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: at24cxx.c,v 1.18 2014/07/25 08:10:37 dholland Exp $    */
+/*     $NetBSD: at24cxx.c,v 1.19 2015/05/10 22:54:06 jmcneill Exp $    */
 
 /*
  * Copyright (c) 2003 Wasabi Systems, Inc.
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: at24cxx.c,v 1.18 2014/07/25 08:10:37 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: at24cxx.c,v 1.19 2015/05/10 22:54:06 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -262,9 +262,6 @@
         */
 
        while (uio->uio_resid > 0 && uio->uio_offset < sc->sc_size) {
-               if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0)
-                       return (error);
-
                a = (int)uio->uio_offset;
                if (sc->sc_cmdlen == 1) {
                        addr = sc->sc_address + (a >> 8);
@@ -274,6 +271,9 @@
                        cmdbuf[0] = AT24CXX_ADDR_HI(a);
                        cmdbuf[1] = AT24CXX_ADDR_LO(a);
                }
+
+               if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0)
+                       return (error);
                if ((error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
                                      addr, cmdbuf, sc->sc_cmdlen,
                                      &ch, 1, 0)) != 0) {
@@ -282,11 +282,11 @@
                            "seeprom_read: byte read failed at 0x%x\n", a);
                        return (error);
                }
+               iic_release_bus(sc->sc_tag, 0);
+
                if ((error = uiomove(&ch, 1, uio)) != 0) {
-                       iic_release_bus(sc->sc_tag, 0);
                        return (error);
                }
-               iic_release_bus(sc->sc_tag, 0);
        }
 
        return (0);
@@ -313,9 +313,6 @@
         */
 
        while (uio->uio_resid > 0 && uio->uio_offset < sc->sc_size) {
-               if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0)
-                       return (error);
-
                a = (int)uio->uio_offset;
                if (sc->sc_cmdlen == 1) {
                        addr = sc->sc_address + (a >> 8);
@@ -329,6 +326,9 @@
                        iic_release_bus(sc->sc_tag, 0);
                        return (error);
                }
+
+               if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0)
+                       return (error);
                if ((error = iic_exec(sc->sc_tag, I2C_OP_WRITE_WITH_STOP,
                                      addr, cmdbuf, sc->sc_cmdlen,
                                      &ch, 1, 0)) != 0) {
@@ -337,13 +337,12 @@
                            "seeprom_write: byte write failed at 0x%x\n", a);
                        return (error);
                }
+               iic_release_bus(sc->sc_tag, 0);
 
                /* Wait until the device commits the byte. */
                if ((error = seeprom_wait_idle(sc)) != 0) {
-                       iic_release_bus(sc->sc_tag, 0);
                        return (error);
                }
-               iic_release_bus(sc->sc_tag, 0);
        }
 
        return (0);
@@ -355,6 +354,7 @@
        uint8_t cmdbuf[2] = { 0, 0 };
        int rv, timeout;
        u_int8_t dummy;
+       int error;
 
        timeout = (1000 / hz) / AT24CXX_WRITE_CYCLE_MS;
        if (timeout == 0)
@@ -366,8 +366,15 @@
         * Read the byte at address 0.  This is just a dummy
         * read to wait for the EEPROM's write cycle to complete.
         */
-       while (iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP, sc->sc_address,
-                       cmdbuf, sc->sc_cmdlen, &dummy, 1, 0)) {
+       for (;;) {
+               if ((error = iic_acquire_bus(sc->sc_tag, 0)) != 0)
+                       return error;
+               error = iic_exec(sc->sc_tag, I2C_OP_READ_WITH_STOP,
+                   sc->sc_address, cmdbuf, sc->sc_cmdlen, &dummy, 1, 0);
+               iic_release_bus(sc->sc_tag, 0);
+               if (error == 0)
+                       break;
+
                rv = tsleep(sc, PRIBIO | PCATCH, "seepromwr", timeout);
                if (rv != EWOULDBLOCK)
                        return (rv);



Home | Main Index | Thread Index | Old Index