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; |
