diff options
Diffstat (limited to 'sound/core/control.c')
-rw-r--r-- | sound/core/control.c | 24 |
1 files changed, 15 insertions, 9 deletions
diff --git a/sound/core/control.c b/sound/core/control.c index 50e7ba66f187..82aa1af1d1d8 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -1203,14 +1203,19 @@ static int snd_ctl_elem_read(struct snd_card *card, const u32 pattern = 0xdeadbeef; int ret; + down_read(&card->controls_rwsem); kctl = snd_ctl_find_id(card, &control->id); - if (kctl == NULL) - return -ENOENT; + if (kctl == NULL) { + ret = -ENOENT; + goto unlock; + } index_offset = snd_ctl_get_ioff(kctl, &control->id); vd = &kctl->vd[index_offset]; - if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_READ) || kctl->get == NULL) - return -EPERM; + if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_READ) || kctl->get == NULL) { + ret = -EPERM; + goto unlock; + } snd_ctl_build_ioff(&control->id, kctl, index_offset); @@ -1220,7 +1225,7 @@ static int snd_ctl_elem_read(struct snd_card *card, info.id = control->id; ret = __snd_ctl_elem_info(card, kctl, &info, NULL); if (ret < 0) - return ret; + goto unlock; #endif if (!snd_ctl_skip_validation(&info)) @@ -1230,7 +1235,7 @@ static int snd_ctl_elem_read(struct snd_card *card, ret = kctl->get(kctl, control); snd_power_unref(card); if (ret < 0) - return ret; + goto unlock; if (!snd_ctl_skip_validation(&info) && sanity_check_elem_value(card, control, &info, pattern) < 0) { dev_err(card->dev, @@ -1238,8 +1243,11 @@ static int snd_ctl_elem_read(struct snd_card *card, control->id.iface, control->id.device, control->id.subdevice, control->id.name, control->id.index); - return -EINVAL; + ret = -EINVAL; + goto unlock; } +unlock: + up_read(&card->controls_rwsem); return ret; } @@ -1253,9 +1261,7 @@ static int snd_ctl_elem_read_user(struct snd_card *card, if (IS_ERR(control)) return PTR_ERR(control); - down_read(&card->controls_rwsem); result = snd_ctl_elem_read(card, control); - up_read(&card->controls_rwsem); if (result < 0) goto error; |