svn commit: r274759 - head/sys/i386/isa

John Baldwin jhb at FreeBSD.org
Thu Nov 20 20:24:31 UTC 2014


Author: jhb
Date: Thu Nov 20 20:24:30 2014
New Revision: 274759
URL: https://svnweb.freebsd.org/changeset/base/274759

Log:
  Lock spic(4) and mark it MPSAFE:
  - Add a per-softc mutex as a driver lock.
  - Use callout(9) instead of timeout(9).
  - Set softc pointer in si_drv1 of cdev instead of looking softc
    up via devclass in cdev methods.
  
  Tested by:	no one

Modified:
  head/sys/i386/isa/spic.c

Modified: head/sys/i386/isa/spic.c
==============================================================================
--- head/sys/i386/isa/spic.c	Thu Nov 20 20:09:18 2014	(r274758)
+++ head/sys/i386/isa/spic.c	Thu Nov 20 20:24:30 2014	(r274759)
@@ -87,7 +87,6 @@ static d_poll_t		spicpoll;
 
 static struct cdevsw spic_cdevsw = {
 	.d_version =	D_VERSION,
-	.d_flags =	D_NEEDGIANT,
 	.d_open =	spicopen,
 	.d_close =	spicclose,
 	.d_read =	spicread,
@@ -106,8 +105,10 @@ struct spic_softc {
 	int sc_opened;
 	int sc_sleeping;
 	int sc_buttonlast;
-	struct callout_handle sc_timeout_ch;
+	struct callout sc_timeout;
+	struct mtx sc_lock;
 	device_t sc_dev;
+	struct cdev *sc_cdev;
 	struct selinfo sc_rsel;
 	u_char sc_buf[SCBUFLEN];
 	int sc_count;
@@ -337,6 +338,8 @@ spic_attach(device_t dev)
 	sc = device_get_softc(dev);
 
 	sc->sc_dev = dev;
+	mtx_init(&sc->sc_lock, "spic", NULL, MTX_DEF);
+	callout_init_mtx(&sc->sc_timeout, &sc->sc_lock, 0);
 	
 	spic_pollrate = (hz/50); /* Every 50th of a second */
 
@@ -345,7 +348,8 @@ spic_attach(device_t dev)
 	spic_call1(sc, 0x92);
 
 	/* There can be only one */
-	make_dev(&spic_cdevsw, 0, 0, 0, 0600, "jogdial");
+	sc->sc_cdev = make_dev(&spic_cdevsw, 0, 0, 0, 0600, "jogdial");
+	sc->sc_cdev->si_drv1 = sc;
 
 	return 0;
 }
@@ -357,6 +361,7 @@ spictimeout(void *arg)
 	u_char b, event, param;
 	int j;
 
+	mtx_assert(&sc->sc_lock, MA_OWNED);
 	if (!sc->sc_opened) {
 		device_printf(sc->sc_dev, "timeout called while closed!\n");
 		return;
@@ -426,7 +431,7 @@ spictimeout(void *arg)
 		}
 	else {
 		/* No event. Wait some more */
-		sc->sc_timeout_ch = timeout(spictimeout, sc, spic_pollrate);
+		callout_reset(&sc->sc_timeout, spic_pollrate, spictimeout, sc);
 		return;
 	}
 
@@ -439,7 +444,7 @@ spictimeout(void *arg)
 	}
 	spic_call2(sc, 0x81, 0xff); /* Clear event */
 
-	sc->sc_timeout_ch = timeout(spictimeout, sc, spic_pollrate);
+	callout_reset(&sc->sc_timeout, spic_pollrate, spictimeout, sc);
 }
 
 static int
@@ -447,17 +452,21 @@ spicopen(struct cdev *dev, int flag, int
 {
 	struct spic_softc *sc;
 
-	sc = devclass_get_softc(spic_devclass, 0);
+	sc = dev->si_drv1;
 
-	if (sc->sc_opened)
-		return EBUSY;
+	mtx_lock(&sc->sc_lock);
+	if (sc->sc_opened) {
+		mtx_unlock(&sc->sc_lock);
+		return (EBUSY);
+	}
 
 	sc->sc_opened++;
 	sc->sc_count=0;
 
 	/* Start the polling */
-	timeout(spictimeout, sc, spic_pollrate);
-	return 0;
+	callout_reset(&sc->sc_timeout, spic_pollrate, spictimeout, sc);
+	mtx_unlock(&sc->sc_lock);
+	return (0);
 }
 
 static int
@@ -465,11 +474,13 @@ spicclose(struct cdev *dev, int flag, in
 {
 	struct spic_softc *sc;
 
-	sc = devclass_get_softc(spic_devclass, 0);
+	sc = dev->si_drv1;
+	mtx_lock(&sc->sc_lock);
 
 	/* Stop polling */
-	untimeout(spictimeout, sc, sc->sc_timeout_ch);
+	callout_stop(&sc->sc_timeout);
 	sc->sc_opened = 0;
+	mtx_unlock(&sc->sc_lock);
 	return 0;
 }
 
@@ -477,34 +488,31 @@ static int
 spicread(struct cdev *dev, struct uio *uio, int flag)
 {
 	struct spic_softc *sc;
-	int l, s, error;
+	int l, error;
 	u_char buf[SCBUFLEN];
 
-	sc = devclass_get_softc(spic_devclass, 0);
+	sc = dev->si_drv1;
 
 	if (uio->uio_resid <= 0) /* What kind of a read is this?! */
-		return 0;
+		return (0);
 
-	s = spltty();
+	mtx_lock(&sc->sc_lock);
 	while (!(sc->sc_count)) {
 		sc->sc_sleeping=1;
-		error = tsleep( sc, PZERO | PCATCH, "jogrea", 0);
+		error = mtx_sleep(sc, &sc->sc_lock, PZERO | PCATCH, "jogrea", 0);
 		sc->sc_sleeping=0;
 		if (error) {
-			splx(s);
-			return error;
+			mtx_unlock(&sc->sc_lock);
+			return (error);
 		}
 	}
-	splx(s);
 
-	s = spltty();
 	l = min(uio->uio_resid, sc->sc_count);
 	bcopy(sc->sc_buf, buf, l);
 	sc->sc_count -= l;
 	bcopy(sc->sc_buf + l, sc->sc_buf, l);
-	splx(s);
-	return uiomove(buf, l, uio);
-
+	mtx_unlock(&sc->sc_lock);
+	return (uiomove(buf, l, uio));
 }
 
 static int
@@ -512,28 +520,28 @@ spicioctl(struct cdev *dev, u_long cmd, 
 {
 	struct spic_softc *sc;
 
-	sc = devclass_get_softc(spic_devclass, 0);
+	sc = dev->si_drv1;
 
-	return EIO;
+	return (EIO);
 }
 
 static int
 spicpoll(struct cdev *dev, int events, struct thread *td)
 {
 	struct spic_softc *sc;
-	int revents = 0, s;
+	int revents = 0;
 
-	sc = devclass_get_softc(spic_devclass, 0);
-	s = spltty();
+	sc = dev->si_drv1;
+	mtx_lock(&sc->sc_lock);
 	if (events & (POLLIN | POLLRDNORM)) {
 		if (sc->sc_count)
 			revents |= events & (POLLIN | POLLRDNORM);
 		else
 			selrecord(td, &sc->sc_rsel); /* Who shall we wake? */
 	}
-	splx(s);
+	mtx_unlock(&sc->sc_lock);
 
-	return revents;
+	return (revents);
 }
 
 


More information about the svn-src-head mailing list