diff --git a/sys/dev/sound/pci/hda/hdaa.c b/sys/dev/sound/pci/hda/hdaa.c --- a/sys/dev/sound/pci/hda/hdaa.c +++ b/sys/dev/sound/pci/hda/hdaa.c @@ -6458,10 +6458,10 @@ device_printf(dev, "Reconfiguration...\n"); ); - bus_topo_lock(); + SND_LOCK(); if ((error = device_delete_children(dev)) != 0) { - bus_topo_unlock(); + SND_UNLOCK(); return (error); } hdaa_lock(devinfo); @@ -6473,7 +6473,7 @@ device_printf(dev, "Reconfiguration done\n"); ); - bus_topo_unlock(); + SND_UNLOCK(); return (0); } diff --git a/sys/dev/sound/pci/hda/hdac.c b/sys/dev/sound/pci/hda/hdac.c --- a/sys/dev/sound/pci/hda/hdac.c +++ b/sys/dev/sound/pci/hda/hdac.c @@ -1401,10 +1401,10 @@ return (0); } - bus_topo_lock(); + SND_LOCK(); if ((err = device_get_children(dev, &devlist, &devcount)) != 0) { - bus_topo_unlock(); + SND_UNLOCK(); return (err); } @@ -1413,7 +1413,7 @@ HDAC_PINDUMP(devlist[i]); hdac_unlock(sc); - bus_topo_unlock(); + SND_UNLOCK(); free(devlist, M_TEMP); return (0); diff --git a/sys/dev/sound/pcm/channel.c b/sys/dev/sound/pcm/channel.c --- a/sys/dev/sound/pcm/channel.c +++ b/sys/dev/sound/pcm/channel.c @@ -128,6 +128,7 @@ struct pcm_channel *c; int i; + SND_LOCK(); for (i = 0; pcm_devclass != NULL && i < devclass_get_maxunit(pcm_devclass); i++) { d = devclass_get_softc(pcm_devclass, i); @@ -146,6 +147,7 @@ PCM_RELEASE(d); PCM_UNLOCK(d); } + SND_UNLOCK(); } static int @@ -166,7 +168,7 @@ return (0); } SYSCTL_PROC(_hw_snd, OID_AUTO, vpc_0db, - CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT, 0, sizeof(int), + CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 0, sizeof(int), sysctl_hw_snd_vpc_0db, "I", "0db relative level"); @@ -186,7 +188,7 @@ return (0); } SYSCTL_PROC(_hw_snd, OID_AUTO, vpc_reset, - CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 0, sizeof(int), + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, 0, sizeof(int), sysctl_hw_snd_vpc_reset, "I", "reset volume on all channels"); diff --git a/sys/dev/sound/pcm/dsp.c b/sys/dev/sound/pcm/dsp.c --- a/sys/dev/sound/pcm/dsp.c +++ b/sys/dev/sound/pcm/dsp.c @@ -1927,7 +1927,7 @@ } return; found: - bus_topo_lock(); + SND_LOCK(); d = devclass_get_softc(pcm_devclass, snd_unit); /* * If we only have a single soundcard attached and we detach it right @@ -1939,7 +1939,7 @@ *dev = d->dsp_dev; dev_ref(*dev); } - bus_topo_unlock(); + SND_UNLOCK(); } static void @@ -2016,6 +2016,7 @@ if (ai->dev == -1 && i_dev->si_devsw != &dsp_cdevsw) return (EINVAL); + SND_LOCK(); for (unit = 0; pcm_devclass != NULL && unit < devclass_get_maxunit(pcm_devclass); unit++) { d = devclass_get_softc(pcm_devclass, unit); @@ -2023,6 +2024,7 @@ if ((ai->dev == -1 && unit == snd_unit) || ai->dev == unit) { dsp_oss_audioinfo_unavail(ai, unit); + SND_UNLOCK(); return (0); } else { d = NULL; @@ -2041,6 +2043,7 @@ d = NULL; } } + SND_UNLOCK(); /* Exhausted the search -- nothing is locked, so return. */ if (d == NULL) @@ -2197,6 +2200,7 @@ * Search for the requested audio device (channel). Start by * iterating over pcm devices. */ + SND_LOCK(); for (unit = 0; pcm_devclass != NULL && unit < devclass_get_maxunit(pcm_devclass); unit++) { d = devclass_get_softc(pcm_devclass, unit); @@ -2346,9 +2350,11 @@ CHN_UNLOCK(ch); PCM_UNLOCK(d); + SND_UNLOCK(); return (0); } + SND_UNLOCK(); /* Exhausted the search -- nothing is locked, so return. */ return (EINVAL); diff --git a/sys/dev/sound/pcm/feeder_rate.c b/sys/dev/sound/pcm/feeder_rate.c --- a/sys/dev/sound/pcm/feeder_rate.c +++ b/sys/dev/sound/pcm/feeder_rate.c @@ -258,6 +258,7 @@ * set resampler quality if and only if it is exist as * part of feeder chains and the channel is idle. */ + SND_LOCK(); for (i = 0; pcm_devclass != NULL && i < devclass_get_maxunit(pcm_devclass); i++) { d = devclass_get_softc(pcm_devclass, i); @@ -279,11 +280,12 @@ PCM_RELEASE(d); PCM_UNLOCK(d); } + SND_UNLOCK(); return (0); } SYSCTL_PROC(_hw_snd, OID_AUTO, feeder_rate_quality, - CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT, 0, sizeof(int), + CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 0, sizeof(int), sysctl_hw_snd_feeder_rate_quality, "I", "sample rate converter quality ("__XSTRING(Z_QUALITY_MIN)"=low .. " __XSTRING(Z_QUALITY_MAX)"=high)"); diff --git a/sys/dev/sound/pcm/mixer.c b/sys/dev/sound/pcm/mixer.c --- a/sys/dev/sound/pcm/mixer.c +++ b/sys/dev/sound/pcm/mixer.c @@ -1362,14 +1362,14 @@ if (*dev != NULL) return; if (strcmp(name, "mixer") == 0) { - bus_topo_lock(); + SND_LOCK(); d = devclass_get_softc(pcm_devclass, snd_unit); /* See related comment in dsp_clone(). */ if (d != NULL && PCM_REGISTERED(d) && d->mixer_dev != NULL) { *dev = d->mixer_dev; dev_ref(*dev); } - bus_topo_unlock(); + SND_UNLOCK(); } } @@ -1444,12 +1444,14 @@ * There's a 1:1 relationship between mixers and PCM devices, so * begin by iterating over PCM devices and search for our mixer. */ + SND_LOCK(); for (i = 0; pcm_devclass != NULL && i < devclass_get_maxunit(pcm_devclass); i++) { d = devclass_get_softc(pcm_devclass, i); if (!PCM_REGISTERED(d)) { if ((mi->dev == -1 && i == snd_unit) || mi->dev == i) { mixer_oss_mixerinfo_unavail(mi, i); + SND_UNLOCK(); return (0); } else continue; @@ -1470,6 +1472,7 @@ if (d->mixer_dev->si_drv1 == NULL) { mixer_oss_mixerinfo_unavail(mi, i); PCM_UNLOCK(d); + SND_UNLOCK(); return (0); } @@ -1550,8 +1553,10 @@ PCM_UNLOCK(d); + SND_UNLOCK(); return (0); } + SND_UNLOCK(); return (EINVAL); } diff --git a/sys/dev/sound/pcm/sound.h b/sys/dev/sound/pcm/sound.h --- a/sys/dev/sound/pcm/sound.h +++ b/sys/dev/sound/pcm/sound.h @@ -71,6 +71,7 @@ #include #include #include +#include #ifndef KOBJMETHOD_END #define KOBJMETHOD_END { NULL, NULL } @@ -160,6 +161,7 @@ #define DSP_DEFAULT_SPEED 8000 +extern struct sx snd_sx; extern int snd_unit; extern int snd_verbose; extern devclass_t pcm_devclass; @@ -257,6 +259,9 @@ #define PCM_MODE_PLAY 0x02 #define PCM_MODE_REC 0x04 +#define SND_LOCK() sx_xlock(&snd_sx) +#define SND_UNLOCK() sx_xunlock(&snd_sx) + #define PCM_LOCKOWNED(d) mtx_owned((d)->lock) #define PCM_LOCK(d) mtx_lock((d)->lock) #define PCM_UNLOCK(d) mtx_unlock((d)->lock) diff --git a/sys/dev/sound/pcm/sound.c b/sys/dev/sound/pcm/sound.c --- a/sys/dev/sound/pcm/sound.c +++ b/sys/dev/sound/pcm/sound.c @@ -50,6 +50,9 @@ int snd_unit = -1; +struct sx snd_sx; +SX_SYSINIT(snd_sx, &snd_sx, "snd sx"); + static int snd_unit_auto = -1; SYSCTL_INT(_hw_snd, OID_AUTO, default_auto, CTLFLAG_RWTUN, &snd_unit_auto, 0, "assign default unit to a newly attached device"); @@ -119,14 +122,16 @@ d = devclass_get_softc(pcm_devclass, unit); if (!PCM_REGISTERED(d) || CHN_EMPTY(d, channels.pcm)) return EINVAL; + SND_LOCK(); snd_unit = unit; snd_unit_auto = 0; + SND_UNLOCK(); } return (error); } /* XXX: do we need a way to let the user change the default unit? */ SYSCTL_PROC(_hw_snd, OID_AUTO, default_unit, - CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_ANYBODY | CTLFLAG_NEEDGIANT, 0, + CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_ANYBODY | CTLFLAG_MPSAFE, 0, sizeof(int), sysctl_hw_snd_default_unit, "I", "default sound device"); @@ -213,6 +218,7 @@ best = -1; bestprio = -100; + SND_LOCK(); for (i = 0; pcm_devclass != NULL && i < devclass_get_maxunit(pcm_devclass); i++) { d = devclass_get_softc(pcm_devclass, i); @@ -228,6 +234,8 @@ bestprio = prio; } } + SND_UNLOCK(); + return (best); } @@ -557,6 +565,7 @@ j = 0; + SND_LOCK(); for (i = 0; pcm_devclass != NULL && i < devclass_get_maxunit(pcm_devclass); i++) { d = devclass_get_softc(pcm_devclass, i); @@ -583,6 +592,7 @@ PCM_UNLOCK(d); } + SND_UNLOCK(); si->numsynths = 0; /* OSSv4 docs: this field is obsolete */ /** @@ -603,9 +613,11 @@ * break if they try to loop through all mixers and some of them are * not available. */ + SND_LOCK(); si->nummixers = devclass_get_maxunit(pcm_devclass); si->numcards = devclass_get_maxunit(pcm_devclass); si->numaudios = devclass_get_maxunit(pcm_devclass); + SND_UNLOCK(); /* OSSv4 docs: Intended only for test apps; API doesn't really have much of a concept of cards. Shouldn't be used by applications. */ @@ -631,6 +643,7 @@ struct snddev_info *d; int i; + SND_LOCK(); for (i = 0; pcm_devclass != NULL && i < devclass_get_maxunit(pcm_devclass); i++) { d = devclass_get_softc(pcm_devclass, i); @@ -658,8 +671,11 @@ PCM_UNLOCK(d); } + SND_UNLOCK(); return (0); } + SND_UNLOCK(); + return (ENXIO); } diff --git a/sys/dev/sound/pcm/vchan.c b/sys/dev/sound/pcm/vchan.c --- a/sys/dev/sound/pcm/vchan.c +++ b/sys/dev/sound/pcm/vchan.c @@ -825,6 +825,7 @@ if (error != 0 || req->newptr == NULL) return (error); + SND_LOCK(); snd_vchans_enable = v >= 1; for (i = 0; pcm_devclass != NULL && @@ -842,11 +843,12 @@ d->flags &= ~(SD_F_PVCHANS | SD_F_RVCHANS); PCM_RELEASE_QUICK(d); } + SND_UNLOCK(); return (0); } SYSCTL_PROC(_hw_snd, OID_AUTO, vchans_enable, - CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT, 0, sizeof(int), + CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 0, sizeof(int), sysctl_hw_snd_vchans_enable, "I", "global virtual channel switch"); void