Date: Tue, 28 Oct 2003 14:24:28 -0500 From: Mathew Kanner <mat@cnd.mcgill.ca> To: freebsd-current@freebsd.org Subject: sound LOR patches Message-ID: <20031028192428.GN31273@cnd.mcgill.ca>
next in thread | raw e-mail | index | archive | help
--mR8QP4gmHujQHb1c Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hello All, I tried to fix some LOR in -current and attached you will find some patches. I sent these to the -sound list but I didn't get a response. (Maybe I should mention that I'm also part of the -sound list). So now I don't know what's going in with sound and -current. Anyway, the fixes are: dsp_open: rearrange to only hold one lock at a time dsp_close: ditto mixer_hwvol_init: delete locking, the only consumer seems to be the ess driver and it only call it a creation time, I think the device will be stable across the sleepable malloc in the dyn. sysctl allocation cmi interrupt routine: Release locks while caller chn_intr, We could either this or do what emu10k1 does which is have no locks at in the interrupt handler. Cheers, --Mat -- I don't even know what street Canada is on. - Al Capone --mR8QP4gmHujQHb1c Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="dspopen_lor.patch" --- dspold.c Sun Sep 14 17:49:38 2003 +++ dsp.c Tue Oct 21 14:38:44 2003 @@ -174,6 +174,8 @@ intrmask_t s; u_int32_t fmt; int devtype; + int rdref; + int error; s = spltty(); d = dsp_get_info(i_dev); @@ -209,6 +211,8 @@ panic("impossible devtype %d", devtype); } + rdref = 0; + /* lock snddev so nobody else can monkey with it */ pcm_lock(d); @@ -251,67 +255,66 @@ return EBUSY; } /* got a channel, already locked for us */ - } - - if (flags & FWRITE) { - /* open for write */ - wrch = pcm_chnalloc(d, PCMDIR_PLAY, td->td_proc->p_pid, -1); - if (!wrch) { - /* no channel available */ - if (flags & FREAD) { - /* just opened a read channel, release it */ - pcm_chnrelease(rdch); - } - /* exit */ - pcm_unlock(d); - splx(s); - return EBUSY; - } - /* got a channel, already locked for us */ - } - - i_dev->si_drv1 = rdch; - i_dev->si_drv2 = wrch; - - /* Bump refcounts, reset and unlock any channels that we just opened, - * and then release device lock. - */ - if (flags & FREAD) { if (chn_reset(rdch, fmt)) { pcm_chnrelease(rdch); i_dev->si_drv1 = NULL; - if (wrch && (flags & FWRITE)) { - pcm_chnrelease(wrch); - i_dev->si_drv2 = NULL; - } pcm_unlock(d); splx(s); return ENODEV; } + if (flags & O_NONBLOCK) rdch->flags |= CHN_F_NBIO; pcm_chnref(rdch, 1); CHN_UNLOCK(rdch); + rdref = 1; + /* + * Record channel created, ref'ed and unlocked + */ } + if (flags & FWRITE) { - if (chn_reset(wrch, fmt)) { - pcm_chnrelease(wrch); - i_dev->si_drv2 = NULL; - if (flags & FREAD) { - CHN_LOCK(rdch); - pcm_chnref(rdch, -1); - pcm_chnrelease(rdch); - i_dev->si_drv1 = NULL; - } - pcm_unlock(d); - splx(s); - return ENODEV; + /* open for write */ + wrch = pcm_chnalloc(d, PCMDIR_PLAY, td->td_proc->p_pid, -1); + error = 0; + + if (!wrch) + error = EBUSY; /* XXX Right return code? */ + else if (chn_reset(wrch, fmt)) + error = ENODEV; + + if (error != 0) { + if (wrch) { + /* + * Free play channel + */ + pcm_chnrelease(wrch); + i_dev->si_drv2 = NULL; } - if (flags & O_NONBLOCK) - wrch->flags |= CHN_F_NBIO; - pcm_chnref(wrch, 1); - CHN_UNLOCK(wrch); + if (rdref) { + /* + * Lock, deref and release previously created record channel + */ + CHN_LOCK(rdch); + pcm_chnref(rdch, -1); + pcm_chnrelease(rdch); + i_dev->si_drv1 = NULL; + } + + pcm_unlock(d); + splx(s); + return error; + } + + if (flags & O_NONBLOCK) + wrch->flags |= CHN_F_NBIO; + pcm_chnref(wrch, 1); + CHN_UNLOCK(wrch); } + + i_dev->si_drv1 = rdch; + i_dev->si_drv2 = wrch; + pcm_unlock(d); splx(s); return 0; --mR8QP4gmHujQHb1c Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="dspclose_lor.patch" --- /home/mat/dsp.c.1.66 Fri Oct 24 18:07:23 2003 +++ /usr/src/sys/dev/sound/pcm/dsp.c Sat Oct 25 00:24:49 2003 @@ -321,7 +321,7 @@ struct pcm_channel *rdch, *wrch; struct snddev_info *d; intrmask_t s; - int exit; + int refs; s = spltty(); d = dsp_get_info(i_dev); @@ -329,53 +329,57 @@ rdch = i_dev->si_drv1; wrch = i_dev->si_drv2; - exit = 0; + refs = 0; - /* decrement refcount for each channel, exit if nonzero */ if (rdch) { CHN_LOCK(rdch); - if (pcm_chnref(rdch, -1) > 0) { - CHN_UNLOCK(rdch); - exit = 1; - } + refs += pcm_chnref(rdch, -1); + CHN_UNLOCK(rdch); } if (wrch) { CHN_LOCK(wrch); - if (pcm_chnref(wrch, -1) > 0) { - CHN_UNLOCK(wrch); - exit = 1; - } - } - if (exit) { - pcm_unlock(d); - splx(s); - return 0; + refs += pcm_chnref(wrch, -1); + CHN_UNLOCK(wrch); } - /* both refcounts are zero, abort and release */ + /* + * If there are no more references, release the channels. + */ + if ((rdch || wrch) && refs == 0) { - if (pcm_getfakechan(d)) - pcm_getfakechan(d)->flags = 0; + if (pcm_getfakechan(d)) + pcm_getfakechan(d)->flags = 0; - i_dev->si_drv1 = NULL; - i_dev->si_drv2 = NULL; + i_dev->si_drv1 = NULL; + i_dev->si_drv2 = NULL; - dsp_set_flags(i_dev, dsp_get_flags(i_dev) & ~SD_F_TRANSIENT); - pcm_unlock(d); + dsp_set_flags(i_dev, dsp_get_flags(i_dev) & ~SD_F_TRANSIENT); - if (rdch) { - chn_abort(rdch); /* won't sleep */ - rdch->flags &= ~(CHN_F_RUNNING | CHN_F_MAPPED | CHN_F_DEAD); - chn_reset(rdch, 0); - pcm_chnrelease(rdch); - } - if (wrch) { - chn_flush(wrch); /* may sleep */ - wrch->flags &= ~(CHN_F_RUNNING | CHN_F_MAPPED | CHN_F_DEAD); - chn_reset(wrch, 0); - pcm_chnrelease(wrch); - } + pcm_unlock(d); + if (rdch) { + CHN_LOCK(rdch); + chn_abort(rdch); /* won't sleep */ + rdch->flags &= ~(CHN_F_RUNNING | CHN_F_MAPPED | CHN_F_DEAD); + chn_reset(rdch, 0); + pcm_chnrelease(rdch); + } + if (wrch) { + CHN_LOCK(wrch); + /* + * XXX: Maybe the right behaviour is to abort on non_block. + * It seems that mplayer flushes the audio queue by quickly + * closing and re-opening. In FBSD, there's a long pause + * while the audio queue flushes that I presume isn't there in + * linux. + */ + chn_flush(wrch); /* may sleep */ + wrch->flags &= ~(CHN_F_RUNNING | CHN_F_MAPPED | CHN_F_DEAD); + chn_reset(wrch, 0); + pcm_chnrelease(wrch); + } + } else + pcm_unlock(d); splx(s); return 0; } --mR8QP4gmHujQHb1c Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="mixerhwvol.patch" --- mixer.c.old Sat Oct 25 00:29:26 2003 +++ mixer.c Sat Oct 25 00:30:06 2003 @@ -319,7 +319,6 @@ pdev = mixer_get_devt(dev); m = pdev->si_drv1; - snd_mtxlock(m->lock); m->hwvol_mixer = SOUND_MIXER_VOLUME; m->hwvol_step = 5; @@ -330,7 +329,6 @@ OID_AUTO, "hwvol_mixer", CTLTYPE_STRING | CTLFLAG_RW, m, 0, sysctl_hw_snd_hwvol_mixer, "A", ""); #endif - snd_mtxunlock(m->lock); return 0; } --mR8QP4gmHujQHb1c Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="cmi_intr.patch" --- /home/mat/cmi.c.1.23 Sat Oct 25 00:22:09 2003 +++ /usr/src/sys/dev/sound/pci/cmi.c Fri Oct 24 23:49:03 2003 @@ -51,7 +51,7 @@ #include "mixer_if.h" -SND_DECLARE_FILE("$FreeBSD: /repoman/r/ncvs/src/sys/dev/sound/pci/cmi.c,v 1.23 2003/09/02 17:30:37 jhb Exp $"); +SND_DECLARE_FILE("$FreeBSD: src/sys/dev/sound/pci/cmi.c,v 1.23 2003/09/02 17:30:37 jhb Exp $"); /* Supported chip ID's */ #define CMI8338A_PCI_ID 0x010013f6 @@ -516,41 +516,41 @@ { struct sc_info *sc = data; u_int32_t intrstat; + u_int32_t toclear; snd_mtxlock(sc->lock); intrstat = cmi_rd(sc, CMPCI_REG_INTR_STATUS, 4); - if ((intrstat & CMPCI_REG_ANY_INTR) == 0) { - goto out; - } - - /* Disable interrupts */ - if (intrstat & CMPCI_REG_CH0_INTR) { - cmi_clr4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE); - } + if ((intrstat & CMPCI_REG_ANY_INTR) != 0) { - if (intrstat & CMPCI_REG_CH1_INTR) { - cmi_clr4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE); - } + toclear = 0; + if (intrstat & CMPCI_REG_CH0_INTR) { + toclear |= CMPCI_REG_CH0_INTR_ENABLE; + //cmi_clr4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE); + } - /* Signal interrupts to channel */ - if (intrstat & CMPCI_REG_CH0_INTR) { - chn_intr(sc->pch.channel); - } + if (intrstat & CMPCI_REG_CH1_INTR) { + toclear |= CMPCI_REG_CH1_INTR_ENABLE; + //cmi_clr4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE); + } - if (intrstat & CMPCI_REG_CH1_INTR) { - chn_intr(sc->rch.channel); - } + if (toclear) { + cmi_clr4(sc, CMPCI_REG_INTR_CTRL, toclear); + snd_mtxunlock(sc->lock); + + /* Signal interrupts to channel */ + if (intrstat & CMPCI_REG_CH0_INTR) { + chn_intr(sc->pch.channel); + } + + if (intrstat & CMPCI_REG_CH1_INTR) { + chn_intr(sc->rch.channel); + } - /* Enable interrupts */ - if (intrstat & CMPCI_REG_CH0_INTR) { - cmi_set4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH0_INTR_ENABLE); - } + snd_mtxlock(sc->lock); + cmi_set4(sc, CMPCI_REG_INTR_CTRL, toclear); - if (intrstat & CMPCI_REG_CH1_INTR) { - cmi_set4(sc, CMPCI_REG_INTR_CTRL, CMPCI_REG_CH1_INTR_ENABLE); + } } - -out: snd_mtxunlock(sc->lock); return; } --mR8QP4gmHujQHb1c--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20031028192428.GN31273>