Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/onewire PR kern/54617: onewire(4):
details: https://anonhg.NetBSD.org/src/rev/17eb40c66afb
branches: trunk
changeset: 460500:17eb40c66afb
user: martin <martin%NetBSD.org@localhost>
date: Fri Oct 25 16:25:14 2019 +0000
description:
PR kern/54617: onewire(4):
- Alter locking strategy to avoid deadlock on detach.
- Auto bus probe chews CPU. Increase interval from 3s to 10s.
- Put temp sensor S/N in dev description so it can be identified.
- Use mutex/condvar.
Patch from Andrew Doran.
diffstat:
sys/dev/onewire/onewire.c | 187 ++++++++++++++++++++++++------------------
sys/dev/onewire/onewirereg.h | 4 +-
sys/dev/onewire/owtemp.c | 28 ++++-
3 files changed, 129 insertions(+), 90 deletions(-)
diffs (truncated from 513 to 300 lines):
diff -r 06e423958b5a -r 17eb40c66afb sys/dev/onewire/onewire.c
--- a/sys/dev/onewire/onewire.c Fri Oct 25 16:22:48 2019 +0000
+++ b/sys/dev/onewire/onewire.c Fri Oct 25 16:25:14 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: onewire.c,v 1.16 2014/07/25 08:10:38 dholland Exp $ */
+/* $NetBSD: onewire.c,v 1.17 2019/10/25 16:25:14 martin Exp $ */
/* $OpenBSD: onewire.c,v 1.1 2006/03/04 16:27:03 grange Exp $ */
/*
@@ -18,7 +18,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: onewire.c,v 1.16 2014/07/25 08:10:38 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: onewire.c,v 1.17 2019/10/25 16:25:14 martin Exp $");
/*
* 1-Wire bus driver.
@@ -30,8 +30,7 @@
#include <sys/device.h>
#include <sys/kernel.h>
#include <sys/kthread.h>
-#include <sys/rwlock.h>
-#include <sys/malloc.h>
+#include <sys/kmem.h>
#include <sys/proc.h>
#include <sys/queue.h>
#include <sys/module.h>
@@ -45,18 +44,16 @@
#define DPRINTF(x)
#endif
-//#define ONEWIRE_MAXDEVS 256
-#define ONEWIRE_MAXDEVS 8
-#define ONEWIRE_SCANTIME 3
+int onewire_maxdevs = 8;
+int onewire_scantime = 10; /* was 3 seconds - too often */
struct onewire_softc {
device_t sc_dev;
-
struct onewire_bus * sc_bus;
- krwlock_t sc_rwlock;
+ kmutex_t sc_lock;
+ kcondvar_t sc_scancv;
struct lwp * sc_thread;
TAILQ_HEAD(, onewire_device) sc_devs;
-
int sc_dying;
};
@@ -64,7 +61,7 @@
TAILQ_ENTRY(onewire_device) d_list;
device_t d_dev;
u_int64_t d_rom;
- int d_present;
+ bool d_present;
};
static int onewire_match(device_t, cfdata_t, void *);
@@ -79,21 +76,6 @@
CFATTACH_DECL_NEW(onewire, sizeof(struct onewire_softc),
onewire_match, onewire_attach, onewire_detach, onewire_activate);
-const struct cdevsw onewire_cdevsw = {
- .d_open = noopen,
- .d_close = noclose,
- .d_read = noread,
- .d_write = nowrite,
- .d_ioctl = noioctl,
- .d_stop = nostop,
- .d_tty = notty,
- .d_poll = nopoll,
- .d_mmap = nommap,
- .d_kqfilter = nokqfilter,
- .d_discard = nodiscard,
- .d_flag = D_OTHER
-};
-
extern struct cfdriver onewire_cd;
static int
@@ -110,14 +92,19 @@
sc->sc_dev = self;
sc->sc_bus = oba->oba_bus;
- rw_init(&sc->sc_rwlock);
+ mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
+ cv_init(&sc->sc_scancv, "owscan");
TAILQ_INIT(&sc->sc_devs);
aprint_normal("\n");
- if (kthread_create(PRI_NONE, 0, NULL, onewire_thread, sc,
- &sc->sc_thread, "%s", device_xname(self)) != 0)
+ if (kthread_create(PRI_NONE, KTHREAD_MUSTJOIN | KTHREAD_MPSAFE, NULL,
+ onewire_thread, sc, &sc->sc_thread, "%s", device_xname(self)) != 0) {
aprint_error_dev(self, "can't create kernel thread\n");
+ /* Normally the kthread destroys these. */
+ mutex_destroy(&sc->sc_lock);
+ cv_destroy(&sc->sc_scancv);
+ }
}
static int
@@ -126,17 +113,17 @@
struct onewire_softc *sc = device_private(self);
int rv;
- sc->sc_dying = 1;
if (sc->sc_thread != NULL) {
- wakeup(sc->sc_thread);
- tsleep(&sc->sc_dying, PWAIT, "owdt", 0);
+ mutex_enter(&sc->sc_lock);
+ sc->sc_dying = 1;
+ cv_broadcast(&sc->sc_scancv);
+ mutex_exit(&sc->sc_lock);
+ /* Must no longer touch sc_lock nor sc_scancv. */
+ kthread_join(sc->sc_thread);
}
- onewire_lock(sc);
//rv = config_detach_children(self, flags);
rv = 0; /* XXX riz */
- onewire_unlock(sc);
- rw_destroy(&sc->sc_rwlock);
return rv;
}
@@ -170,7 +157,7 @@
(uint)ONEWIRE_ROM_FAMILY_TYPE(oa->oa_rom));
else
aprint_normal("\"%s\"", famname);
- aprint_normal(" sn %012llx", ONEWIRE_ROM_SN(oa->oa_rom));
+ aprint_normal(" sn %012" PRIx64, ONEWIRE_ROM_SN(oa->oa_rom));
if (pnp != NULL)
aprint_normal(" at %s", pnp);
@@ -192,7 +179,7 @@
{
struct onewire_softc *sc = arg;
- rw_enter(&sc->sc_rwlock, RW_WRITER);
+ mutex_enter(&sc->sc_lock);
}
void
@@ -200,7 +187,7 @@
{
struct onewire_softc *sc = arg;
- rw_exit(&sc->sc_rwlock);
+ mutex_exit(&sc->sc_lock);
}
int
@@ -209,6 +196,8 @@
struct onewire_softc *sc = arg;
struct onewire_bus *bus = sc->sc_bus;
+ KASSERT(mutex_owned(&sc->sc_lock));
+
return bus->bus_reset(bus->bus_cookie);
}
@@ -218,6 +207,8 @@
struct onewire_softc *sc = arg;
struct onewire_bus *bus = sc->sc_bus;
+ KASSERT(mutex_owned(&sc->sc_lock));
+
return bus->bus_bit(bus->bus_cookie, value);
}
@@ -229,6 +220,8 @@
uint8_t value = 0;
int i;
+ KASSERT(mutex_owned(&sc->sc_lock));
+
if (bus->bus_read_byte != NULL)
return bus->bus_read_byte(bus->bus_cookie);
@@ -245,6 +238,8 @@
struct onewire_bus *bus = sc->sc_bus;
int i;
+ KASSERT(mutex_owned(&sc->sc_lock));
+
if (bus->bus_write_byte != NULL)
return bus->bus_write_byte(bus->bus_cookie, value);
@@ -259,6 +254,8 @@
struct onewire_bus *bus = sc->sc_bus;
int rv;
+ KASSERT(mutex_owned(&sc->sc_lock));
+
if (bus->bus_triplet != NULL)
return bus->bus_triplet(bus->bus_cookie, dir);
@@ -283,29 +280,38 @@
void
onewire_read_block(void *arg, void *buf, int len)
{
+ struct onewire_softc *sc = arg;
uint8_t *p = buf;
+ KASSERT(mutex_owned(&sc->sc_lock));
+
while (len--)
- *p++ = onewire_read_byte(arg);
+ *p++ = onewire_read_byte(sc);
}
void
onewire_write_block(void *arg, const void *buf, int len)
{
+ struct onewire_softc *sc = arg;
const uint8_t *p = buf;
+ KASSERT(mutex_owned(&sc->sc_lock));
+
while (len--)
- onewire_write_byte(arg, *p++);
+ onewire_write_byte(sc, *p++);
}
void
onewire_matchrom(void *arg, u_int64_t rom)
{
+ struct onewire_softc *sc = arg;
int i;
- onewire_write_byte(arg, ONEWIRE_CMD_MATCH_ROM);
+ KASSERT(mutex_owned(&sc->sc_lock));
+
+ onewire_write_byte(sc, ONEWIRE_CMD_MATCH_ROM);
for (i = 0; i < 8; i++)
- onewire_write_byte(arg, (rom >> (i * 8)) & 0xff);
+ onewire_write_byte(sc, (rom >> (i * 8)) & 0xff);
}
static void
@@ -313,13 +319,17 @@
{
struct onewire_softc *sc = arg;
+ mutex_enter(&sc->sc_lock);
while (!sc->sc_dying) {
onewire_scan(sc);
- tsleep(sc->sc_thread, PWAIT, "owidle", ONEWIRE_SCANTIME * hz);
+ (void)cv_timedwait(&sc->sc_scancv, &sc->sc_lock,
+ onewire_scantime * hz);
}
+ mutex_exit(&sc->sc_lock);
- sc->sc_thread = NULL;
- wakeup(&sc->sc_dying);
+ /* Caller has set sc_dying and will no longer touch these. */
+ cv_destroy(&sc->sc_scancv);
+ mutex_destroy(&sc->sc_lock);
kthread_exit(0);
}
@@ -328,29 +338,28 @@
{
struct onewire_device *d, *next, *nd;
struct onewire_attach_args oa;
- device_t dev;
int search = 1, count = 0, present;
int dir, rv;
uint64_t mask, rom = 0, lastrom;
uint8_t data[8];
int i, i0 = -1, lastd = -1;
- TAILQ_FOREACH(d, &sc->sc_devs, d_list)
- d->d_present = 0;
+ TAILQ_FOREACH(d, &sc->sc_devs, d_list) {
+ d->d_present = false;
+ KASSERT(d->d_dev != NULL);
+ }
- while (search && count++ < ONEWIRE_MAXDEVS) {
- /* XXX: yield processor */
- tsleep(sc, PWAIT, "owscan", hz / 10);
+ KASSERT(mutex_owned(&sc->sc_lock));
+ KASSERT(curlwp == sc->sc_thread);
+ while (search && count++ < onewire_maxdevs) {
/*
* Reset the bus. If there's no presence pulse
* don't search for any devices.
*/
- onewire_lock(sc);
if (onewire_reset(sc) != 0) {
DPRINTF(("%s: scan: no presence pulse\n",
device_xname(sc->sc_dev)));
- onewire_unlock(sc);
break;
Home |
Main Index |
Thread Index |
Old Index