diff options
author | imp <imp@FreeBSD.org> | 2005-03-11 07:03:46 +0000 |
---|---|---|
committer | imp <imp@FreeBSD.org> | 2005-03-11 07:03:46 +0000 |
commit | 86f7da92483e4eaba01249f78c04cea68b99edfc (patch) | |
tree | f128ab4f5c217ee2ec8754a4670bd67da5005a44 /sys/dev/ppbus/pps.c | |
parent | 675c170c5a83e24727118404ee2f7de1dbcd0132 (diff) | |
download | FreeBSD-src-86f7da92483e4eaba01249f78c04cea68b99edfc.zip FreeBSD-src-86f7da92483e4eaba01249f78c04cea68b99edfc.tar.gz |
Make the pps interrupt register as MPSAFE and FAST. Use a spin lock
to syncrhonize access to the data as a result. This makes the pps
less likely to miss the 1ms pulse that I'm feeding it, but not
entirely reliable yet on my 133MHz P5.
Reviewed by: phk
Diffstat (limited to 'sys/dev/ppbus/pps.c')
-rw-r--r-- | sys/dev/ppbus/pps.c | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/sys/dev/ppbus/pps.c b/sys/dev/ppbus/pps.c index 2582aa1..c66e39d 100644 --- a/sys/dev/ppbus/pps.c +++ b/sys/dev/ppbus/pps.c @@ -46,6 +46,7 @@ struct pps_data { struct callout_handle timeout; int lastdata; + struct mtx mtx; struct resource *intr_resource; /* interrupt resource */ void *intr_cookie; /* interrupt registration cookie */ }; @@ -64,7 +65,6 @@ static d_ioctl_t ppsioctl; static struct cdevsw pps_cdevsw = { .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, .d_open = ppsopen, .d_close = ppsclose, .d_ioctl = ppsioctl, @@ -110,6 +110,7 @@ ppsattach(device_t dev) intptr_t irq; int i, unit, zero = 0; + mtx_init(&sc->mtx, device_get_nameunit(dev), "pps", MTX_SPIN); /* retrieve the ppbus irq */ BUS_READ_IVAR(ppbus, dev, PPBUS_IVAR_IRQ, &irq); @@ -203,9 +204,9 @@ ppsopen(struct cdev *dev, int flags, int fmt, struct thread *td) return (EINTR); /* attach the interrupt handler */ - if ((error = BUS_SETUP_INTR(ppbus, ppsdev, sc->intr_resource, - INTR_TYPE_TTY, ppsintr, ppsdev, - &sc->intr_cookie))) { + if ((error = bus_setup_intr(ppsdev, sc->intr_resource, + (INTR_TYPE_TTY | INTR_MPSAFE | INTR_FAST), ppsintr, + ppsdev, &sc->intr_cookie))) { ppb_release_bus(ppbus, ppsdev); return (error); } @@ -280,14 +281,18 @@ ppsintr(void *arg) struct pps_data *sc = DEVTOSOFTC(ppsdev); device_t ppbus = sc->ppbus; + mtx_lock(&sc->mtx); pps_capture(&sc->pps[0]); - if (!(ppb_rstr(ppbus) & nACK)) + if (!(ppb_rstr(ppbus) & nACK)) { + mtx_unlock(&sc->mtx); return; + } if (sc->pps[0].ppsparam.mode & PPS_ECHOASSERT) ppb_wctr(ppbus, IRQENABLE | AUTOFEED); pps_event(&sc->pps[0], PPS_CAPTUREASSERT); if (sc->pps[0].ppsparam.mode & PPS_ECHOASSERT) ppb_wctr(ppbus, IRQENABLE); + mtx_unlock(&sc->mtx); } static int @@ -295,8 +300,12 @@ ppsioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags, struct thread *t { struct pps_data *sc = dev->si_drv1; int subdev = (intptr_t)dev->si_drv2; + int err; - return (pps_ioctl(cmd, data, &sc->pps[subdev])); + mtx_lock(&sc->mtx); + err = pps_ioctl(cmd, data, &sc->pps[subdev]); + mtx_unlock(&sc->mtx); + return (err); } static device_method_t pps_methods[] = { |