From owner-svn-src-head@FreeBSD.ORG Thu Nov 20 20:24:31 2014 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 7E6021D1; Thu, 20 Nov 2014 20:24:31 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 5E3DA828; Thu, 20 Nov 2014 20:24:31 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id sAKKOVCa094930; Thu, 20 Nov 2014 20:24:31 GMT (envelope-from jhb@FreeBSD.org) Received: (from jhb@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id sAKKOVgn094929; Thu, 20 Nov 2014 20:24:31 GMT (envelope-from jhb@FreeBSD.org) Message-Id: <201411202024.sAKKOVgn094929@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: jhb set sender to jhb@FreeBSD.org using -f From: John Baldwin Date: Thu, 20 Nov 2014 20:24:31 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r274759 - head/sys/i386/isa X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 20 Nov 2014 20:24:31 -0000 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); }