Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F145273160
D10264.1777558220.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
11 KB
Referenced Files
None
Subscribers
None
D10264.1777558220.diff
View Options
Index: sys/dev/atkbdc/psm.c
===================================================================
--- sys/dev/atkbdc/psm.c
+++ sys/dev/atkbdc/psm.c
@@ -371,6 +371,7 @@
/* driver control block */
struct psm_softc { /* Driver status information */
int unit;
+ struct mtx mtx; /* Driver`s mutex */
struct selinfo rsel; /* Process selecting for Input */
u_char state; /* Mouse driver state */
int config; /* driver configuration flags */
@@ -553,8 +554,12 @@
static int doopen(struct psm_softc *, int);
static int reinitialize(struct psm_softc *, int);
static char *model_name(int);
+static void psm_lock(struct psm_softc *);
+static void psm_unlock(struct psm_softc *);
+static void psm_lock_assert(struct psm_softc *);
static void psmsoftintr(void *);
static void psmsoftintridle(void *);
+static void psmintr_locked(void *);
static void psmintr(void *);
static void psmtimeout(void *);
static int timeelapsed(const struct timeval *, int, int,
@@ -665,7 +670,6 @@
static struct cdevsw psm_cdevsw = {
.d_version = D_VERSION,
- .d_flags = D_NEEDGIANT,
.d_open = psmopen,
.d_close = psmclose,
.d_read = psmread,
@@ -1055,6 +1059,7 @@
{
int stat[3];
+ psm_lock_assert(sc);
kbdc_lock_assert(sc->kbdc);
/*
@@ -1159,11 +1164,11 @@
{
int err;
int c;
- int s;
+
+ psm_lock_assert(sc);
/* don't let anybody mess with the aux device */
kbdc_lock(sc->kbdc);
- s = spltty();
/* block our watchdog timer */
sc->watchdog = FALSE;
@@ -1182,7 +1187,6 @@
KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT |
KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
/* CONTROLLER ERROR */
- splx(s);
kbdc_unlock(sc->kbdc);
log(LOG_ERR,
"psm%d: unable to set the command byte (reinitialize).\n",
@@ -1217,7 +1221,6 @@
err = ENXIO;
}
}
- splx(s);
/* restore the driver state */
if ((sc->state & PSM_OPEN) && (err == 0)) {
@@ -1243,6 +1246,27 @@
return (err);
}
+static void
+psm_lock(struct psm_softc *sc)
+{
+
+ mtx_lock(&sc->mtx);
+}
+
+static void
+psm_unlock(struct psm_softc *sc)
+{
+
+ mtx_unlock(&sc->mtx);
+}
+
+static void
+psm_lock_assert(struct psm_softc *sc)
+{
+
+ mtx_assert(&sc->mtx, MA_OWNED);
+}
+
/* psm driver entry points */
static void
@@ -1606,16 +1630,17 @@
/* Setup initial state */
sc->state = PSM_VALID;
- callout_init(&sc->callout, 0);
- callout_init(&sc->softcallout, 0);
+ mtx_init(&sc->mtx, "psm lock", NULL, MTX_DEF);
+ callout_init_mtx(&sc->callout, &sc->mtx, 0);
+ callout_init_mtx(&sc->softcallout, &sc->mtx, 0);
/* Setup our interrupt handler */
rid = KBDC_RID_AUX;
sc->intr = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
if (sc->intr == NULL)
return (ENXIO);
- error = bus_setup_intr(dev, sc->intr, INTR_TYPE_TTY, NULL, psmintr, sc,
- &sc->ih);
+ error = bus_setup_intr(dev, sc->intr, INTR_TYPE_TTY | INTR_MPSAFE,
+ NULL, psmintr, sc, &sc->ih);
if (error) {
bus_release_resource(dev, SYS_RES_IRQ, rid, sc->intr);
return (error);
@@ -1682,8 +1707,11 @@
destroy_dev(sc->dev);
destroy_dev(sc->bdev);
- callout_drain(&sc->callout);
- callout_drain(&sc->softcallout);
+ psm_lock(sc);
+ callout_stop(&sc->callout);
+ callout_stop(&sc->softcallout);
+ psm_unlock(sc);
+ mtx_destroy(&sc->mtx);
return (0);
}
@@ -1702,9 +1730,13 @@
return (ENXIO);
}
+ psm_lock(sc);
+
/* Disallow multiple opens */
- if (sc->state & PSM_OPEN)
+ if (sc->state & PSM_OPEN) {
+ psm_unlock(sc);
return (EBUSY);
+ }
device_busy(devclass_get_device(psm_devclass, sc->unit));
@@ -1746,6 +1778,7 @@
KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
/* CONTROLLER ERROR; do you know how to get out of this? */
kbdc_unlock(sc->kbdc);
+ psm_unlock(sc);
log(LOG_ERR,
"psm%d: unable to set the command byte (psmopen).\n",
sc->unit);
@@ -1759,6 +1792,7 @@
if (err == 0)
sc->state |= PSM_OPEN;
kbdc_unlock(sc->kbdc);
+ psm_unlock(sc);
return (err);
}
@@ -1769,6 +1803,8 @@
int stat[3];
int command_byte;
+ psm_lock(sc);
+
/* don't let timeout routines in the keyboard driver to poll the kbdc */
kbdc_lock(sc->kbdc);
@@ -1776,6 +1812,7 @@
command_byte = get_controller_command_byte(sc->kbdc);
if (command_byte == -1) {
kbdc_unlock(sc->kbdc);
+ psm_unlock(sc);
return (EIO);
}
@@ -1847,6 +1884,7 @@
sc->state &= ~PSM_OPEN;
kbdc_unlock(sc->kbdc);
device_unbusy(devclass_get_device(psm_devclass, sc->unit));
+ psm_unlock(sc);
return (0);
}
@@ -1918,36 +1956,33 @@
struct psm_softc *sc = dev->si_drv1;
u_char buf[PSM_SMALLBUFSIZE];
int error = 0;
- int s;
int l;
if ((sc->state & PSM_VALID) == 0)
return (EIO);
/* block until mouse activity occurred */
- s = spltty();
+ psm_lock(sc);
while (sc->queue.count <= 0) {
if (dev != sc->bdev) {
- splx(s);
+ psm_unlock(sc);
return (EWOULDBLOCK);
}
sc->state |= PSM_ASLP;
- error = tsleep(sc, PZERO | PCATCH, "psmrea", 0);
+ error = mtx_sleep(sc, &sc->mtx, PZERO | PCATCH, "psmrea", 0);
sc->state &= ~PSM_ASLP;
if (error) {
- splx(s);
+ psm_unlock(sc);
return (error);
} else if ((sc->state & PSM_VALID) == 0) {
/* the device disappeared! */
- splx(s);
+ psm_unlock(sc);
return (EIO);
}
}
- splx(s);
/* copy data to the user land */
while ((sc->queue.count > 0) && (uio->uio_resid > 0)) {
- s = spltty();
l = imin(sc->queue.count, uio->uio_resid);
if (l > sizeof(buf))
l = sizeof(buf);
@@ -1961,11 +1996,13 @@
bcopy(&sc->queue.buf[sc->queue.head], &buf[0], l);
sc->queue.count -= l;
sc->queue.head = (sc->queue.head + l) % sizeof(sc->queue.buf);
- splx(s);
+ psm_unlock(sc);
error = uiomove(buf, l, uio);
+ psm_lock(sc);
if (error)
break;
}
+ psm_unlock(sc);
return (error);
}
@@ -1973,19 +2010,18 @@
static int
block_mouse_data(struct psm_softc *sc, int *c)
{
- int s;
+ psm_lock(sc);
kbdc_lock(sc->kbdc);
- s = spltty();
*c = get_controller_command_byte(sc->kbdc);
if ((*c == -1) || !set_controller_command_byte(sc->kbdc,
kbdc_get_device_mask(sc->kbdc),
KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT |
KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
/* this is CONTROLLER ERROR */
- splx(s);
kbdc_unlock(sc->kbdc);
+ psm_unlock(sc);
return (EIO);
}
@@ -2004,7 +2040,6 @@
empty_aux_buffer(sc->kbdc, 0); /* flush the queue */
read_aux_data_no_wait(sc->kbdc); /* throw away data if any */
flushpackets(sc);
- splx(s);
return (0);
}
@@ -2013,6 +2048,8 @@
dropqueue(struct psm_softc *sc)
{
+ psm_lock_assert(sc);
+
sc->queue.count = 0;
sc->queue.head = 0;
sc->queue.tail = 0;
@@ -2027,6 +2064,8 @@
flushpackets(struct psm_softc *sc)
{
+ psm_lock_assert(sc);
+
dropqueue(sc);
bzero(&sc->pqueue, sizeof(sc->pqueue));
}
@@ -2055,6 +2094,7 @@
}
kbdc_unlock(sc->kbdc);
+ psm_unlock(sc);
return (error);
}
@@ -2084,7 +2124,10 @@
kbdc_unlock(sc->kbdc);
VLOG(2, (LOG_DEBUG,
"psm: cmd 0x%x failed.\n", buf[i]));
- return (reinitialize(sc, FALSE));
+ psm_lock(sc);
+ error = reinitialize(sc, FALSE);
+ psm_unlock(sc);
+ return (error);
}
}
kbdc_unlock(sc->kbdc);
@@ -2107,39 +2150,38 @@
int stat[3];
int command_byte;
int error = 0;
- int s;
/* Perform IOCTL command */
switch (cmd) {
case OLD_MOUSE_GETHWINFO:
- s = spltty();
+ psm_lock(sc);
((old_mousehw_t *)addr)->buttons = sc->hw.buttons;
((old_mousehw_t *)addr)->iftype = sc->hw.iftype;
((old_mousehw_t *)addr)->type = sc->hw.type;
((old_mousehw_t *)addr)->hwid = sc->hw.hwid & 0x00ff;
- splx(s);
+ psm_unlock(sc);
break;
case MOUSE_GETHWINFO:
- s = spltty();
+ psm_lock(sc);
*(mousehw_t *)addr = sc->hw;
if (sc->mode.level == PSM_LEVEL_BASE)
((mousehw_t *)addr)->model = MOUSE_MODEL_GENERIC;
- splx(s);
+ psm_unlock(sc);
break;
case MOUSE_SYN_GETHWINFO:
- s = spltty();
+ psm_lock(sc);
if (sc->synhw.infoMajor >= 4)
*(synapticshw_t *)addr = sc->synhw;
else
error = EINVAL;
- splx(s);
+ psm_unlock(sc);
break;
case OLD_MOUSE_GETMODE:
- s = spltty();
+ psm_lock(sc);
switch (sc->mode.level) {
case PSM_LEVEL_BASE:
((old_mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2;
@@ -2155,11 +2197,11 @@
((old_mousemode_t *)addr)->rate = sc->mode.rate;
((old_mousemode_t *)addr)->resolution = sc->mode.resolution;
((old_mousemode_t *)addr)->accelfactor = sc->mode.accelfactor;
- splx(s);
+ psm_unlock(sc);
break;
case MOUSE_GETMODE:
- s = spltty();
+ psm_lock(sc);
*(mousemode_t *)addr = sc->mode;
if ((sc->flags & PSM_NEED_SYNCBITS) != 0) {
((mousemode_t *)addr)->syncmask[0] = 0;
@@ -2185,7 +2227,7 @@
((mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2;
break;
}
- splx(s);
+ psm_unlock(sc);
break;
case OLD_MOUSE_SETMODE:
@@ -2265,12 +2307,10 @@
set_mouse_scaling(sc->kbdc, 1);
get_mouse_status(sc->kbdc, stat, 0, 3);
- s = spltty();
sc->mode.rate = mode.rate;
sc->mode.resolution = mode.resolution;
sc->mode.accelfactor = mode.accelfactor;
sc->mode.level = mode.level;
- splx(s);
unblock_mouse_data(sc, command_byte);
break;
@@ -2287,7 +2327,7 @@
break;
case MOUSE_GETSTATUS:
- s = spltty();
+ psm_lock(sc);
status = sc->status;
sc->status.flags = 0;
sc->status.obutton = sc->status.button;
@@ -2295,7 +2335,7 @@
sc->status.dx = 0;
sc->status.dy = 0;
sc->status.dz = 0;
- splx(s);
+ psm_unlock(sc);
*(mousestatus_t *)addr = status;
break;
@@ -2303,11 +2343,11 @@
case MOUSE_GETVARS:
var = (mousevar_t *)addr;
bzero(var, sizeof(*var));
- s = spltty();
+ psm_lock(sc);
var->var[0] = MOUSE_VARS_PS2_SIG;
var->var[1] = sc->config;
var->var[2] = sc->flags;
- splx(s);
+ psm_unlock(sc);
break;
case MOUSE_SETVARS:
@@ -2426,16 +2466,13 @@
psmtimeout(void *arg)
{
struct psm_softc *sc;
- int s;
sc = (struct psm_softc *)arg;
- s = spltty();
if (sc->watchdog) {
VLOG(4, (LOG_DEBUG, "psm%d: lost interrupt?\n", sc->unit));
- psmintr(sc);
+ psmintr_locked(sc);
}
sc->watchdog = TRUE;
- splx(s);
callout_reset(&sc->callout, hz, psmtimeout, sc);
}
@@ -2496,13 +2533,14 @@
}
static void
-psmintr(void *arg)
+psmintr_locked(void *arg)
{
struct psm_softc *sc = arg;
struct timeval now;
int c;
packetbuf_t *pb;
+ psm_lock_assert(sc);
/* read until there is nothing to read */
while((c = psm_read_aux_data(sc->kbdc)) != -1) {
@@ -2653,6 +2691,16 @@
}
static void
+psmintr(void *arg)
+{
+ struct psm_softc *sc = arg;
+
+ psm_lock(sc);
+ psmintr_locked(sc);
+ psm_unlock(sc);
+}
+
+static void
proc_mmanplus(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms,
int *x, int *y, int *z)
{
@@ -4137,6 +4185,8 @@
struct psm_softc *sc = arg;
packetbuf_t *pb;
+ psm_lock_assert(sc);
+
/* Invoke soft handler only when pqueue is empty. Otherwise it will be
* invoked from psmintr soon with pqueue filled with real data */
if (sc->pqueue_start == sc->pqueue_end &&
@@ -4176,11 +4226,11 @@
struct psm_softc *sc = arg;
mousestatus_t ms;
packetbuf_t *pb;
- int x, y, z, c, l, s;
+ int x, y, z, c, l;
- getmicrouptime(&sc->lastsoftintr);
+ psm_lock_assert(sc);
- s = spltty();
+ getmicrouptime(&sc->lastsoftintr);
do {
pb = &sc->pqueue[sc->pqueue_start];
@@ -4438,25 +4488,23 @@
VLOG(2, (LOG_DEBUG, "softintr: callout set: %d ticks\n",
tvtohz(&sc->idletimeout)));
}
- splx(s);
}
static int
psmpoll(struct cdev *dev, int events, struct thread *td)
{
struct psm_softc *sc = dev->si_drv1;
- int s;
int revents = 0;
/* Return true if a mouse event available */
- s = spltty();
+ psm_lock(sc);
if (events & (POLLIN | POLLRDNORM)) {
if (sc->queue.count > 0)
revents |= events & (POLLIN | POLLRDNORM);
else
selrecord(td, &sc->rsel);
}
- splx(s);
+ psm_unlock(sc);
return (revents);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Apr 30, 2:10 PM (4 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28511759
Default Alt Text
D10264.1777558220.diff (11 KB)
Attached To
Mode
D10264: psm(4), evdev support part 2: psm softc locking
Attached
Detach File
Event Timeline
Log In to Comment