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 @@ -6463,10 +6463,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); @@ -6478,7 +6478,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 @@ -1403,10 +1403,10 @@ return (0); } - bus_topo_lock(); + SND_LOCK(); if ((err = device_get_children(dev, &devlist, &devcount)) != 0) { - bus_topo_unlock(); + SND_UNLOCK(); return (err); } @@ -1415,7 +1415,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 @@ -1959,7 +1959,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 @@ -1971,7 +1971,7 @@ *dev = d->dsp_dev; dev_ref(*dev); } - bus_topo_unlock(); + SND_UNLOCK(); } static void @@ -2068,6 +2068,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); @@ -2075,6 +2076,7 @@ if ((ai->dev == -1 && unit == snd_unit) || ai->dev == unit) { dsp_oss_audioinfo_unavail(ai, unit); + SND_UNLOCK(); return (0); } else { d = NULL; @@ -2093,6 +2095,7 @@ d = NULL; } } + SND_UNLOCK(); /* Exhausted the search -- nothing is locked, so return. */ if (d == NULL) @@ -2252,6 +2255,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); @@ -2406,9 +2410,12 @@ PCM_UNLOCK(d); - if (devname != NULL) + if (devname != NULL) { + 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); @@ -280,10 +281,12 @@ 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) || PCM_DETACHING(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 } @@ -237,6 +238,7 @@ #define DSP_DEFAULT_SPEED 8000 +extern struct sx snd_sx; extern int pcm_veto_load; extern int snd_unit; extern int snd_verbose; @@ -335,6 +337,9 @@ void sound_oss_sysinfo(oss_sysinfo *); int sound_oss_card_info(oss_card_info *); +#define SND_LOCK() sx_xlock(&snd_sx) +#define SND_UNLOCK() sx_xunlock(&snd_sx) + #define PCM_MODE_MIXER 0x01 #define PCM_MODE_PLAY 0x02 #define PCM_MODE_REC 0x04 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 @@ -52,6 +52,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"); @@ -177,14 +180,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"); @@ -333,6 +338,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); @@ -348,6 +354,8 @@ bestprio = prio; } } + SND_UNLOCK(); + return (best); } @@ -721,6 +729,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); @@ -747,6 +756,7 @@ PCM_UNLOCK(d); } + SND_UNLOCK(); si->numsynths = 0; /* OSSv4 docs: this field is obsolete */ /** @@ -767,9 +777,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. */ @@ -795,6 +807,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); @@ -822,8 +835,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 @@ -1065,6 +1065,7 @@ if (v > SND_MAXVCHANS) v = SND_MAXVCHANS; snd_maxautovchans = v; + SND_LOCK(); for (i = 0; pcm_devclass != NULL && i < devclass_get_maxunit(pcm_devclass); i++) { d = devclass_get_softc(pcm_devclass, i); @@ -1074,11 +1075,12 @@ vchan_setmaxauto(d, v); PCM_RELEASE_QUICK(d); } + SND_UNLOCK(); } return (error); } SYSCTL_PROC(_hw_snd, OID_AUTO, maxautovchans, - CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT, 0, sizeof(int), + CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 0, sizeof(int), sysctl_hw_snd_maxautovchans, "I", "maximum virtual channel"); void