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/8acc117f64da
branches: trunk
changeset: 338112:8acc117f64da
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 3b044bfbd4f4 -r 8acc117f64da 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