Date: Thu, 29 Jun 2017 00:29:15 +0000 (UTC) From: Ian Lepore <ian@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r320460 - head/sys/dev/iicbus Message-ID: <201706290029.v5T0TFlB094107@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: ian Date: Thu Jun 29 00:29:15 2017 New Revision: 320460 URL: https://svnweb.freebsd.org/changeset/base/320460 Log: If an i2c transfer ends due to error, issue a stop on the bus even if the nostop option is set, if a start was issued. The nostop option doesn't mean "never issue a stop" it means "only issue a stop after the last in a series of transfers". If the transfer ends due to error, then that was the last transfer in the series, and a stop is required. Before this change, any error during a transfer when nostop is set would effectively hang the bus, because sc->started would never get cleared, and that caused all future calls to iicbus_start() to return an error because it looked like the bus was already active. (Unrelated errors in handling the nostop option, to be addressed separately, could lead to this bus hang condition even on busses that don't set the nostop option.) Modified: head/sys/dev/iicbus/iiconf.c Modified: head/sys/dev/iicbus/iiconf.c ============================================================================== --- head/sys/dev/iicbus/iiconf.c Wed Jun 28 21:45:13 2017 (r320459) +++ head/sys/dev/iicbus/iiconf.c Thu Jun 29 00:29:15 2017 (r320460) @@ -419,7 +419,7 @@ iicbus_transfer_gen(device_t dev, struct iic_msg *msgs { int i, error, lenread, lenwrote, nkid, rpstart, addr; device_t *children, bus; - bool nostop; + bool nostop, started; if ((error = device_get_children(dev, &children, &nkid)) != 0) return (IIC_ERESOURCE); @@ -431,6 +431,7 @@ iicbus_transfer_gen(device_t dev, struct iic_msg *msgs rpstart = 0; free(children, M_TEMP); nostop = iicbus_get_nostop(dev); + started = false; for (i = 0, error = 0; i < nmsgs && error == 0; i++) { addr = msgs[i].slave; if (msgs[i].flags & IIC_M_RD) @@ -443,9 +444,10 @@ iicbus_transfer_gen(device_t dev, struct iic_msg *msgs error = iicbus_repeated_start(bus, addr, 0); else error = iicbus_start(bus, addr, 0); + if (error != 0) + break; + started = true; } - if (error != 0) - break; if (msgs[i].flags & IIC_M_RD) error = iicbus_read(bus, msgs[i].buf, msgs[i].len, @@ -464,7 +466,7 @@ iicbus_transfer_gen(device_t dev, struct iic_msg *msgs iicbus_stop(bus); } } - if (error != 0 && !nostop) + if (error != 0 && started) iicbus_stop(bus); return (error); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201706290029.v5T0TFlB094107>