diff options
Diffstat (limited to 'sound/core/control.c')
-rw-r--r-- | sound/core/control.c | 39 |
1 files changed, 29 insertions, 10 deletions
diff --git a/sound/core/control.c b/sound/core/control.c index 0c29679a8576..574745314e70 100644 --- a/sound/core/control.c +++ b/sound/core/control.c | |||
@@ -309,28 +309,29 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol) | |||
309 | { | 309 | { |
310 | struct snd_ctl_elem_id id; | 310 | struct snd_ctl_elem_id id; |
311 | unsigned int idx; | 311 | unsigned int idx; |
312 | int err = -EINVAL; | ||
312 | 313 | ||
313 | snd_assert(card != NULL, return -EINVAL); | ||
314 | if (! kcontrol) | 314 | if (! kcontrol) |
315 | return -EINVAL; | 315 | return err; |
316 | snd_assert(kcontrol->info != NULL, return -EINVAL); | 316 | snd_assert(card != NULL, goto error); |
317 | snd_assert(kcontrol->info != NULL, goto error); | ||
317 | id = kcontrol->id; | 318 | id = kcontrol->id; |
318 | down_write(&card->controls_rwsem); | 319 | down_write(&card->controls_rwsem); |
319 | if (snd_ctl_find_id(card, &id)) { | 320 | if (snd_ctl_find_id(card, &id)) { |
320 | up_write(&card->controls_rwsem); | 321 | up_write(&card->controls_rwsem); |
321 | snd_ctl_free_one(kcontrol); | ||
322 | snd_printd(KERN_ERR "control %i:%i:%i:%s:%i is already present\n", | 322 | snd_printd(KERN_ERR "control %i:%i:%i:%s:%i is already present\n", |
323 | id.iface, | 323 | id.iface, |
324 | id.device, | 324 | id.device, |
325 | id.subdevice, | 325 | id.subdevice, |
326 | id.name, | 326 | id.name, |
327 | id.index); | 327 | id.index); |
328 | return -EBUSY; | 328 | err = -EBUSY; |
329 | goto error; | ||
329 | } | 330 | } |
330 | if (snd_ctl_find_hole(card, kcontrol->count) < 0) { | 331 | if (snd_ctl_find_hole(card, kcontrol->count) < 0) { |
331 | up_write(&card->controls_rwsem); | 332 | up_write(&card->controls_rwsem); |
332 | snd_ctl_free_one(kcontrol); | 333 | err = -ENOMEM; |
333 | return -ENOMEM; | 334 | goto error; |
334 | } | 335 | } |
335 | list_add_tail(&kcontrol->list, &card->controls); | 336 | list_add_tail(&kcontrol->list, &card->controls); |
336 | card->controls_count += kcontrol->count; | 337 | card->controls_count += kcontrol->count; |
@@ -340,6 +341,10 @@ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol) | |||
340 | for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++) | 341 | for (idx = 0; idx < kcontrol->count; idx++, id.index++, id.numid++) |
341 | snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id); | 342 | snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id); |
342 | return 0; | 343 | return 0; |
344 | |||
345 | error: | ||
346 | snd_ctl_free_one(kcontrol); | ||
347 | return err; | ||
343 | } | 348 | } |
344 | 349 | ||
345 | /** | 350 | /** |
@@ -658,7 +663,11 @@ static int snd_ctl_elem_info_user(struct snd_ctl_file *ctl, | |||
658 | 663 | ||
659 | if (copy_from_user(&info, _info, sizeof(info))) | 664 | if (copy_from_user(&info, _info, sizeof(info))) |
660 | return -EFAULT; | 665 | return -EFAULT; |
661 | result = snd_ctl_elem_info(ctl, &info); | 666 | snd_power_lock(ctl->card); |
667 | result = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0, NULL); | ||
668 | if (result >= 0) | ||
669 | result = snd_ctl_elem_info(ctl, &info); | ||
670 | snd_power_unlock(ctl->card); | ||
662 | if (result >= 0) | 671 | if (result >= 0) |
663 | if (copy_to_user(_info, &info, sizeof(info))) | 672 | if (copy_to_user(_info, &info, sizeof(info))) |
664 | return -EFAULT; | 673 | return -EFAULT; |
@@ -708,7 +717,11 @@ static int snd_ctl_elem_read_user(struct snd_card *card, | |||
708 | kfree(control); | 717 | kfree(control); |
709 | return -EFAULT; | 718 | return -EFAULT; |
710 | } | 719 | } |
711 | result = snd_ctl_elem_read(card, control); | 720 | snd_power_lock(card); |
721 | result = snd_power_wait(card, SNDRV_CTL_POWER_D0, NULL); | ||
722 | if (result >= 0) | ||
723 | result = snd_ctl_elem_read(card, control); | ||
724 | snd_power_unlock(card); | ||
712 | if (result >= 0) | 725 | if (result >= 0) |
713 | if (copy_to_user(_control, control, sizeof(*control))) | 726 | if (copy_to_user(_control, control, sizeof(*control))) |
714 | result = -EFAULT; | 727 | result = -EFAULT; |
@@ -758,6 +771,7 @@ static int snd_ctl_elem_write_user(struct snd_ctl_file *file, | |||
758 | struct snd_ctl_elem_value __user *_control) | 771 | struct snd_ctl_elem_value __user *_control) |
759 | { | 772 | { |
760 | struct snd_ctl_elem_value *control; | 773 | struct snd_ctl_elem_value *control; |
774 | struct snd_card *card; | ||
761 | int result; | 775 | int result; |
762 | 776 | ||
763 | control = kmalloc(sizeof(*control), GFP_KERNEL); | 777 | control = kmalloc(sizeof(*control), GFP_KERNEL); |
@@ -767,7 +781,12 @@ static int snd_ctl_elem_write_user(struct snd_ctl_file *file, | |||
767 | kfree(control); | 781 | kfree(control); |
768 | return -EFAULT; | 782 | return -EFAULT; |
769 | } | 783 | } |
770 | result = snd_ctl_elem_write(file->card, file, control); | 784 | card = file->card; |
785 | snd_power_lock(card); | ||
786 | result = snd_power_wait(card, SNDRV_CTL_POWER_D0, NULL); | ||
787 | if (result >= 0) | ||
788 | result = snd_ctl_elem_write(card, file, control); | ||
789 | snd_power_unlock(card); | ||
771 | if (result >= 0) | 790 | if (result >= 0) |
772 | if (copy_to_user(_control, control, sizeof(*control))) | 791 | if (copy_to_user(_control, control, sizeof(*control))) |
773 | result = -EFAULT; | 792 | result = -EFAULT; |