Page MenuHomeFreeBSD

D10264.1777558220.diff
No OneTemporary

Size
11 KB
Referenced Files
None
Subscribers
None

D10264.1777558220.diff

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

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)

Event Timeline