summaryrefslogtreecommitdiff
path: root/sys/dev/pckbc/pms.c
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2014-08-19 12:24:05 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2014-08-19 12:24:05 +0000
commit270a6d367d98a55cfeb38319c73a001964f6b820 (patch)
treea94240e4d94977483b2b512b0a263bd4751db126 /sys/dev/pckbc/pms.c
parent79fb1f9e55548321a1a0f2ffd24b189ed13e188b (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.c25
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