diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2014-08-19 12:24:05 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2014-08-19 12:24:05 +0000 |
commit | 270a6d367d98a55cfeb38319c73a001964f6b820 (patch) | |
tree | a94240e4d94977483b2b512b0a263bd4751db126 /sys/dev/pckbc/pms.c | |
parent | 79fb1f9e55548321a1a0f2ffd24b189ed13e188b (diff) |
Make sure state changes are properly serialized.
When pms(4) is attached to a touchpad it generally presents two different
wsmouse(4) devices: one for the touchpad itself and one for the clitpad
and/or some interleaved packets. But since both devices are writing to
the same pckbc slot, a race can occur if they try to change the state at
the same time.
So prevent two process opening the two /dev/wsmouse* node at the same time
to corrupt the magic sequences needed to enable/disable the touchpad.
ok schadchin@
Diffstat (limited to 'sys/dev/pckbc/pms.c')
-rw-r--r-- | sys/dev/pckbc/pms.c | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/sys/dev/pckbc/pms.c b/sys/dev/pckbc/pms.c index 77904ae771e..c0df81b23ae 100644 --- a/sys/dev/pckbc/pms.c +++ b/sys/dev/pckbc/pms.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pms.c,v 1.52 2014/07/12 18:48:52 tedu Exp $ */ +/* $OpenBSD: pms.c,v 1.53 2014/08/19 12:24:04 mpi Exp $ */ /* $NetBSD: psm.c,v 1.11 2000/06/05 22:20:57 sommerfeld Exp $ */ /*- @@ -26,6 +26,7 @@ #include <sys/param.h> #include <sys/systm.h> +#include <sys/rwlock.h> #include <sys/device.h> #include <sys/ioctl.h> #include <sys/malloc.h> @@ -148,6 +149,8 @@ struct pms_softc { /* driver status information */ #define PMS_STATE_ENABLED 1 #define PMS_STATE_SUSPENDED 2 + struct rwlock sc_state_lock; + int sc_dev_enable; #define PMS_DEV_IGNORE 0x00 #define PMS_DEV_PRIMARY 0x01 @@ -662,6 +665,8 @@ pmsattach(struct device *parent, struct device *self, void *aux) a.accessops = &pms_accessops; a.accesscookie = sc; + rw_init(&sc->sc_state_lock, "pmsst"); + /* * Attach the wsmouse, saving a handle to it. * Note that we don't need to check this pointer against NULL @@ -762,8 +767,13 @@ int pms_enable(void *v) { struct pms_softc *sc = v; + int rv; - return pms_change_state(sc, PMS_STATE_ENABLED, PMS_DEV_PRIMARY); + rw_enter_write(&sc->sc_state_lock); + rv = pms_change_state(sc, PMS_STATE_ENABLED, PMS_DEV_PRIMARY); + rw_exit_write(&sc->sc_state_lock); + + return (rv); } void @@ -771,7 +781,9 @@ pms_disable(void *v) { struct pms_softc *sc = v; + rw_enter_write(&sc->sc_state_lock); pms_change_state(sc, PMS_STATE_DISABLED, PMS_DEV_PRIMARY); + rw_exit_write(&sc->sc_state_lock); } int @@ -789,8 +801,13 @@ int pms_sec_enable(void *v) { struct pms_softc *sc = v; + int rv; + + rw_enter_write(&sc->sc_state_lock); + rv = pms_change_state(sc, PMS_STATE_ENABLED, PMS_DEV_SECONDARY); + rw_exit_write(&sc->sc_state_lock); - return (pms_change_state(sc, PMS_STATE_ENABLED, PMS_DEV_SECONDARY)); + return (rv); } void @@ -798,7 +815,9 @@ pms_sec_disable(void *v) { struct pms_softc *sc = v; + rw_enter_write(&sc->sc_state_lock); pms_change_state(sc, PMS_STATE_DISABLED, PMS_DEV_SECONDARY); + rw_exit_write(&sc->sc_state_lock); } int |