mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
ALSA: compress: pin card module while stream is open
Take a module reference in snd_compr_open() and release it in snd_compr_free(). This pins the card driver module for the lifetime of an open compress stream and prevents card removal while the stream file is still in use. Adjust the open() cleanup paths to drop the added module reference only when it was acquired, and keep release ordering safe by dropping the module reference before freeing stream data. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com> Reviewed-by: Liam Girdwood <liam.r.girdwood@intel.com> Reviewed-by: Takashi Iwai <tiwai@suse.de> Link: https://patch.msgid.link/20261007084955.1256-2-peter.ujfalusi@linux.intel.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
a90ee4305c
commit
59b7978580
|
|
@ -75,11 +75,11 @@ static inline void snd_compr_task_free_all(struct snd_compr_stream *stream) { }
|
|||
static int snd_compr_open(struct inode *inode, struct file *f)
|
||||
{
|
||||
struct snd_compr *compr;
|
||||
struct snd_compr_file *data;
|
||||
struct snd_compr_runtime *runtime;
|
||||
struct snd_compr_file *data = NULL;
|
||||
struct snd_compr_runtime *runtime = NULL;
|
||||
enum snd_compr_direction dirn;
|
||||
int maj = imajor(inode);
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
if ((f->f_flags & O_ACCMODE) == O_WRONLY)
|
||||
dirn = SND_COMPRESS_PLAYBACK;
|
||||
|
|
@ -101,16 +101,21 @@ static int snd_compr_open(struct inode *inode, struct file *f)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!try_module_get(compr->card->module)) {
|
||||
snd_card_unref(compr->card);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (dirn != compr->direction) {
|
||||
pr_err("this device doesn't support this direction\n");
|
||||
snd_card_unref(compr->card);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto __error;
|
||||
}
|
||||
|
||||
data = kzalloc_obj(*data);
|
||||
if (!data) {
|
||||
snd_card_unref(compr->card);
|
||||
return -ENOMEM;
|
||||
ret = -ENOMEM;
|
||||
goto __error;
|
||||
}
|
||||
|
||||
INIT_DELAYED_WORK(&data->stream.error_work, error_delayed_work);
|
||||
|
|
@ -121,9 +126,8 @@ static int snd_compr_open(struct inode *inode, struct file *f)
|
|||
data->stream.device = compr;
|
||||
runtime = kzalloc_obj(*runtime);
|
||||
if (!runtime) {
|
||||
kfree(data);
|
||||
snd_card_unref(compr->card);
|
||||
return -ENOMEM;
|
||||
ret = -ENOMEM;
|
||||
goto __error;
|
||||
}
|
||||
runtime->state = SNDRV_PCM_STATE_OPEN;
|
||||
init_waitqueue_head(&runtime->sleep);
|
||||
|
|
@ -134,9 +138,12 @@ static int snd_compr_open(struct inode *inode, struct file *f)
|
|||
f->private_data = (void *)data;
|
||||
scoped_guard(mutex, &compr->lock)
|
||||
ret = compr->ops->open(&data->stream);
|
||||
|
||||
__error:
|
||||
if (ret) {
|
||||
kfree(runtime);
|
||||
kfree(data);
|
||||
module_put(compr->card->module);
|
||||
}
|
||||
snd_card_unref(compr->card);
|
||||
return ret;
|
||||
|
|
@ -164,6 +171,7 @@ static int snd_compr_free(struct inode *inode, struct file *f)
|
|||
data->stream.ops->free(&data->stream);
|
||||
if (!data->stream.runtime->dma_buffer_p)
|
||||
kfree(data->stream.runtime->buffer);
|
||||
module_put(data->stream.device->card->module);
|
||||
kfree(data->stream.runtime);
|
||||
kfree(data);
|
||||
return 0;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user