[PATCH]: Keep sound-module usage correct, even if audio_open fails

Chris Rankin (rankinc@zipworld.com.au)
Thu, 11 Jan 2001 00:12:10 +0000 (GMT)


Hi,
I noticed that if you try to (e.g.) play two WAV file simultaneously,
then not only does the second one fail ("Device or resource busy", of
course) but the sound-card module's usage count breaks.

Here is a patch. And Alan, since you seem to be the person collecting
these sound patches, I should point out that this patch to
drivers/sound/audio.c completely replaces the patch to audio.c that I
submitted earlier. That patch was related to the coprocessor module
locking, but this new patch has reworked the way that audio_open()
cleans up after itself anyway. This clean-up now includes the
coprocessor too.

Cheers,
Chris

--- linux-vanilla/drivers/sound/audio.c Fri Aug 11 16:26:43 2000
+++ linux-2.4.0-ac3/drivers/sound/audio.c Wed Jan 10 23:53:23 2001
@@ -21,6 +21,9 @@
* Daniel Rodriksson: reworked the use of the device specific copy_user
* still generic
* Horst von Brand: Add missing #include <linux/string.h>
+ * Chris Rankin : Update the module-usage counter for the coprocessor,
+ * and decrement the counters again if we cannot open
+ * the audio device.
*/

#include <linux/stddef.h>
@@ -71,6 +74,8 @@
int bits;
int dev_type = dev & 0x0f;
int mode = translate_mode(file);
+ const struct audio_driver *driver;
+ const struct coproc_operations *coprocessor;

dev = dev >> 4;

@@ -82,18 +87,20 @@
if (dev < 0 || dev >= num_audiodevs)
return -ENXIO;

- if (audio_devs[dev]->d->owner)
- __MOD_INC_USE_COUNT (audio_devs[dev]->d->owner);
+ driver = audio_devs[dev]->d;
+ if (driver->owner)
+ __MOD_INC_USE_COUNT(driver->owner);

if ((ret = DMAbuf_open(dev, mode)) < 0)
- return ret;
+ goto error_1;

- if (audio_devs[dev]->coproc) {
- if ((ret = audio_devs[dev]->coproc->
- open(audio_devs[dev]->coproc->devc, COPR_PCM)) < 0) {
- audio_release(dev, file);
+ if ( (coprocessor = audio_devs[dev]->coproc) != NULL ) {
+ if (coprocessor->owner)
+ __MOD_INC_USE_COUNT(coprocessor->owner);
+
+ if ((ret = coprocessor->open(coprocessor->devc, COPR_PCM)) < 0) {
printk(KERN_WARNING "Sound: Can't access coprocessor device\n");
- return ret;
+ goto error_2;
}
}

@@ -106,6 +113,20 @@

audio_devs[dev]->audio_mode = AM_NONE;

+ return 0;
+
+ /*
+ * Clean-up stack: this is what needs (un)doing if
+ * we can't open the audio device ...
+ */
+ error_2:
+ if (coprocessor->owner)
+ __MOD_DEC_USE_COUNT(coprocessor->owner);
+ DMAbuf_release(dev, mode);
+
+ error_1:
+ if (driver->owner)
+ __MOD_DEC_USE_COUNT(driver->owner);

return ret;
}
@@ -156,7 +177,8 @@

void audio_release(int dev, struct file *file)
{
- int mode = translate_mode(file);
+ const struct coproc_operations *coprocessor;
+ int mode = translate_mode(file);

dev = dev >> 4;

@@ -176,8 +198,12 @@
if (mode & OPEN_WRITE)
sync_output(dev);

- if (audio_devs[dev]->coproc)
- audio_devs[dev]->coproc->close(audio_devs[dev]->coproc->devc, COPR_PCM);
+ if ( (coprocessor = audio_devs[dev]->coproc) != NULL ) {
+ coprocessor->close(coprocessor->devc, COPR_PCM);
+
+ if (coprocessor->owner)
+ __MOD_DEC_USE_COUNT(coprocessor->owner);
+ }
DMAbuf_release(dev, mode);

if (audio_devs[dev]->d->owner)
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/