summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authornetchild <netchild@FreeBSD.org>2005-10-05 20:05:52 +0000
committernetchild <netchild@FreeBSD.org>2005-10-05 20:05:52 +0000
commitcb93bb507cc2412e0ec94e5ec2b08f49fb2a5ee6 (patch)
tree5fd656442001e4fd5ca3781e1d7f5708ec96a952 /sys
parenta04280c7babdec77fca1ced01b30fcc2c35642d3 (diff)
downloadFreeBSD-src-cb93bb507cc2412e0ec94e5ec2b08f49fb2a5ee6.zip
FreeBSD-src-cb93bb507cc2412e0ec94e5ec2b08f49fb2a5ee6.tar.gz
- Locking improvements.
- Don't keep the SPDIF state in the driver private struct since it can be overriden by hand with pciconf(8), query it when needed instead. Regarding the locking I let Ariff explain it himself: ---snip--- About the locking, that is what I'm intended to do since the beginning. The reason I'm not putting that along since my first patchset was because several people especially from amd46 camp reported that it cause lots of LORs, which is weird considering that I've never encounter such in a pretty much strict locking environment (i386). However, since our previous discussion with Pyun YongHyeon about strict locking, I've decided to bring it back for all the affected drivers, not just for es137x. It turns out that the root of the problem was within dsp.c during device open, which has been fixed since dsp.c revision 1.84. ---snip--- Submitted by: Ariff Abdullah <skywizard@MyBSD.org.my>
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/sound/pci/als4000.c15
-rw-r--r--sys/dev/sound/pci/via8233.c44
-rw-r--r--sys/dev/sound/pci/via82c686.c10
3 files changed, 47 insertions, 22 deletions
diff --git a/sys/dev/sound/pci/als4000.c b/sys/dev/sound/pci/als4000.c
index 5693370..2df70dc 100644
--- a/sys/dev/sound/pci/als4000.c
+++ b/sys/dev/sound/pci/als4000.c
@@ -271,9 +271,12 @@ static int
alschan_getptr(kobj_t obj, void *data)
{
struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
int32_t pos, sz;
+ snd_mtxlock(sc->lock);
pos = als_gcr_rd(ch->parent, ch->gcr_fifo_status) & 0xffff;
+ snd_mtxunlock(sc->lock);
sz = sndbuf_getsize(ch->buffer);
return (2 * sz - pos - 1) % sz;
}
@@ -386,7 +389,9 @@ static int
alspchan_trigger(kobj_t obj, void *data, int go)
{
struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ snd_mtxlock(sc->lock);
switch(go) {
case PCMTRIG_START:
als_playback_start(ch);
@@ -395,6 +400,7 @@ alspchan_trigger(kobj_t obj, void *data, int go)
als_playback_stop(ch);
break;
}
+ snd_mtxunlock(sc->lock);
return 0;
}
@@ -476,7 +482,9 @@ static int
alsrchan_trigger(kobj_t obj, void *data, int go)
{
struct sc_chinfo *ch = data;
+ struct sc_info *sc = ch->parent;
+ snd_mtxlock(sc->lock);
switch(go) {
case PCMTRIG_START:
als_capture_start(ch);
@@ -485,6 +493,7 @@ alsrchan_trigger(kobj_t obj, void *data, int go)
als_capture_stop(ch);
break;
}
+ snd_mtxunlock(sc->lock);
return 0;
}
@@ -889,9 +898,11 @@ als_pci_suspend(device_t dev)
{
struct sc_info *sc = pcm_getdevinfo(dev);
+ snd_mtxlock(sc->lock);
sc->pch.dma_was_active = als_playback_stop(&sc->pch);
sc->rch.dma_was_active = als_capture_stop(&sc->rch);
als_uninit(sc);
+ snd_mtxunlock(sc->lock);
return 0;
}
@@ -901,13 +912,16 @@ als_pci_resume(device_t dev)
struct sc_info *sc = pcm_getdevinfo(dev);
+ snd_mtxlock(sc->lock);
if (als_init(sc) != 0) {
device_printf(dev, "unable to reinitialize the card\n");
+ snd_mtxunlock(sc->lock);
return ENXIO;
}
if (mixer_reinit(dev) != 0) {
device_printf(dev, "unable to reinitialize the mixer\n");
+ snd_mtxunlock(sc->lock);
return ENXIO;
}
@@ -918,6 +932,7 @@ als_pci_resume(device_t dev)
if (sc->rch.dma_was_active) {
als_capture_start(&sc->rch);
}
+ snd_mtxunlock(sc->lock);
return 0;
}
diff --git a/sys/dev/sound/pci/via8233.c b/sys/dev/sound/pci/via8233.c
index d262613..19e3507 100644
--- a/sys/dev/sound/pci/via8233.c
+++ b/sys/dev/sound/pci/via8233.c
@@ -100,7 +100,7 @@ struct via_info {
struct ac97_info *codec;
unsigned int bufsz;
- int spdif_en, dxs_src;
+ int dxs_src;
struct via_chinfo pch[NDXSCHANS + NMSGDCHANS];
struct via_chinfo rch[NWRCHANS];
@@ -127,13 +127,15 @@ sysctl_via8233_spdif_enable(SYSCTL_HANDLER_ARGS)
{
struct via_info *via;
device_t dev;
- int err, new_en, r;
+ uint32_t r;
+ int err, new_en;
dev = oidp->oid_arg1;
via = pcm_getdevinfo(dev);
snd_mtxlock(via->lock);
- new_en = via->spdif_en;
+ r = pci_read_config(dev, VIA_PCI_SPDIF, 1);
snd_mtxunlock(via->lock);
+ new_en = (r & VIA_SPDIF_EN) ? 1 : 0;
err = sysctl_handle_int(oidp, &new_en, sizeof(new_en), req);
if (err || req->newptr == NULL)
@@ -141,12 +143,11 @@ sysctl_via8233_spdif_enable(SYSCTL_HANDLER_ARGS)
if (new_en < 0 || new_en > 1)
return EINVAL;
- snd_mtxlock(via->lock);
- via->spdif_en = new_en;
-
- r = pci_read_config(dev, VIA_PCI_SPDIF, 1) & ~VIA_SPDIF_EN;
if (new_en)
r |= VIA_SPDIF_EN;
+ else
+ r &= ~VIA_SPDIF_EN;
+ snd_mtxlock(via->lock);
pci_write_config(dev, VIA_PCI_SPDIF, r, 1);
snd_mtxunlock(via->lock);
@@ -184,13 +185,6 @@ static void
via_init_sysctls(device_t dev)
{
#ifdef SND_DYNSYSCTL
- struct via_info *via;
- int r;
-
- via = pcm_getdevinfo(dev);
- r = pci_read_config(dev, VIA_PCI_SPDIF, 1);
- via->spdif_en = (r & VIA_SPDIF_EN) ? 1 : 0;
-
SYSCTL_ADD_PROC(snd_sysctl_tree(dev),
SYSCTL_CHILDREN(snd_sysctl_tree_top(dev)),
OID_AUTO, "spdif_enabled",
@@ -206,7 +200,7 @@ via_init_sysctls(device_t dev)
#endif
}
-static u_int32_t
+static __inline u_int32_t
via_rd(struct via_info *via, int regno, int size)
{
switch (size) {
@@ -221,7 +215,7 @@ via_rd(struct via_info *via, int regno, int size)
}
}
-static void
+static __inline void
via_wr(struct via_info *via, int regno, u_int32_t data, int size)
{
@@ -347,7 +341,9 @@ via8233wr_setformat(kobj_t obj, void *data, u_int32_t format)
f |= WR_FORMAT_STEREO;
if (format & AFMT_S16_LE)
f |= WR_FORMAT_16BIT;
+ snd_mtxlock(via->lock);
via_wr(via, VIA_WR0_FORMAT, f, 4);
+ snd_mtxunlock(via->lock);
return 0;
}
@@ -360,6 +356,7 @@ via8233dxs_setformat(kobj_t obj, void *data, u_int32_t format)
u_int32_t r, v;
r = ch->rbase + VIA8233_RP_DXS_RATEFMT;
+ snd_mtxlock(via->lock);
v = via_rd(via, r, 4);
v &= ~(VIA8233_DXS_RATEFMT_STEREO | VIA8233_DXS_RATEFMT_16BIT);
@@ -368,6 +365,7 @@ via8233dxs_setformat(kobj_t obj, void *data, u_int32_t format)
if (format & AFMT_16BIT)
v |= VIA8233_DXS_RATEFMT_16BIT;
via_wr(via, r, v, 4);
+ snd_mtxunlock(via->lock);
return 0;
}
@@ -389,8 +387,10 @@ via8233msgd_setformat(kobj_t obj, void *data, u_int32_t format)
s |= SLOT3(1) | SLOT4(1);
}
+ snd_mtxlock(via->lock);
via_wr(via, VIA_MC_SLOT_SELECT, s, 4);
via_wr(via, VIA_MC_SGD_FORMAT, v, 1);
+ snd_mtxunlock(via->lock);
return 0;
}
@@ -418,12 +418,14 @@ via8233dxs_setspeed(kobj_t obj, void *data, u_int32_t speed)
u_int32_t r, v;
r = ch->rbase + VIA8233_RP_DXS_RATEFMT;
+ snd_mtxlock(via->lock);
v = via_rd(via, r, 4) & ~VIA8233_DXS_RATEFMT_48K;
/* Careful to avoid overflow (divide by 48 per vt8233c docs) */
v |= VIA8233_DXS_RATEFMT_48K * (speed / 48) / (48000 / 48);
via_wr(via, r, v, 4);
+ snd_mtxunlock(via->lock);
return speed;
}
@@ -505,7 +507,9 @@ via8233chan_getptr(kobj_t obj, void *data)
u_int32_t v, index, count;
int ptr;
+ snd_mtxlock(via->lock);
v = via_rd(via, ch->rbase + VIA_RP_CURRENT_COUNT, 4);
+ snd_mtxunlock(via->lock);
index = v >> 24; /* Last completed buffer */
count = v & 0x00ffffff; /* Bytes remaining */
ptr = (index + 1) * ch->blksz - count;
@@ -540,13 +544,13 @@ via8233wr_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
struct via_info *via = devinfo;
struct via_chinfo *ch = &via->rch[c->num];
- snd_mtxlock(via->lock);
ch->parent = via;
ch->channel = c;
ch->buffer = b;
ch->dir = dir;
ch->rbase = VIA_WR_BASE(c->num);
+ snd_mtxlock(via->lock);
via_wr(via, ch->rbase + VIA_WR_RP_SGD_FORMAT, WR_FIFO_ENABLE, 1);
snd_mtxunlock(via->lock);
@@ -568,7 +572,6 @@ via8233dxs_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
struct via_info *via = devinfo;
struct via_chinfo *ch = &via->pch[c->num];
- snd_mtxlock(via->lock);
ch->parent = via;
ch->channel = c;
ch->buffer = b;
@@ -579,6 +582,7 @@ via8233dxs_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
* channels. We therefore want to align first DXS channel to
* DXS3.
*/
+ snd_mtxlock(via->lock);
ch->rbase = VIA_DXS_BASE(NDXSCHANS - 1 - via->n_dxs_registered);
via->n_dxs_registered++;
snd_mtxunlock(via->lock);
@@ -601,13 +605,11 @@ via8233msgd_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
struct via_info *via = devinfo;
struct via_chinfo *ch = &via->pch[c->num];
- snd_mtxlock(via->lock);
ch->parent = via;
ch->channel = c;
ch->buffer = b;
ch->dir = dir;
ch->rbase = VIA_MC_SGD_STATUS;
- snd_mtxunlock(via->lock);
if (sndbuf_alloc(ch->buffer, via->parent_dmat, via->bufsz) != 0)
return NULL;
@@ -642,6 +644,7 @@ via8233chan_trigger(kobj_t obj, void* data, int go)
struct via_chinfo *ch = data;
struct via_info *via = ch->parent;
+ snd_mtxlock(via->lock);
switch(go) {
case PCMTRIG_START:
via_buildsgdt(ch);
@@ -658,6 +661,7 @@ via8233chan_trigger(kobj_t obj, void* data, int go)
via8233chan_reset(via, ch);
break;
}
+ snd_mtxunlock(via->lock);
return 0;
}
diff --git a/sys/dev/sound/pci/via82c686.c b/sys/dev/sound/pci/via82c686.c
index 0be2fd0..d0a910c 100644
--- a/sys/dev/sound/pci/via82c686.c
+++ b/sys/dev/sound/pci/via82c686.c
@@ -99,7 +99,7 @@ static u_int32_t via_fmt[] = {
static struct pcmchan_caps via_vracaps = {4000, 48000, via_fmt, 0};
static struct pcmchan_caps via_caps = {48000, 48000, via_fmt, 0};
-static u_int32_t
+static __inline u_int32_t
via_rd(struct via_info *via, int regno, int size)
{
@@ -116,7 +116,7 @@ via_rd(struct via_info *via, int regno, int size)
}
-static void
+static __inline void
via_wr(struct via_info *via, int regno, u_int32_t data, int size)
{
@@ -290,10 +290,12 @@ viachan_setformat(kobj_t obj, void *data, u_int32_t format)
mode_set |= VIA_RPMODE_16BIT;
DEB(printf("set format: dir = %d, format=%x\n", ch->dir, format));
+ snd_mtxlock(via->lock);
mode = via_rd(via, ch->mode, 1);
mode &= ~(VIA_RPMODE_16BIT | VIA_RPMODE_STEREO);
mode |= mode_set;
via_wr(via, ch->mode, mode, 1);
+ snd_mtxunlock(via->lock);
return 0;
}
@@ -346,12 +348,14 @@ viachan_trigger(kobj_t obj, void *data, int go)
ado = ch->sgd_table;
DEB(printf("ado located at va=%p pa=%x\n", ado, sgd_addr));
+ snd_mtxlock(via->lock);
if (go == PCMTRIG_START) {
via_buildsgdt(ch);
via_wr(via, ch->base, sgd_addr, 4);
via_wr(via, ch->ctrl, VIA_RPCTRL_START, 1);
} else
via_wr(via, ch->ctrl, VIA_RPCTRL_TERMINATE, 1);
+ snd_mtxunlock(via->lock);
DEB(printf("viachan_trigger: go=%d\n", go));
return 0;
@@ -367,11 +371,13 @@ viachan_getptr(kobj_t obj, void *data)
int ptr, base, base1, len, seg;
ado = ch->sgd_table;
+ snd_mtxlock(via->lock);
base1 = via_rd(via, ch->base, 4);
len = via_rd(via, ch->count, 4);
base = via_rd(via, ch->base, 4);
if (base != base1) /* Avoid race hazard */
len = via_rd(via, ch->count, 4);
+ snd_mtxunlock(via->lock);
DEB(printf("viachan_getptr: len / base = %x / %x\n", len, base));
OpenPOWER on IntegriCloud