- 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>
This commit is contained in:
Alexander Leidinger 2005-10-05 20:05:52 +00:00
parent dcbde45390
commit e7d2d131f1
3 changed files with 47 additions and 22 deletions

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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));