#ifdef CONFIG_PM
unsigned int power_state; /* power state */
- struct mutex power_lock; /* power lock */
wait_queue_head_t power_sleep;
#endif
#define dev_to_snd_card(p) container_of(p, struct snd_card, card_dev)
#ifdef CONFIG_PM
-static inline void snd_power_lock(struct snd_card *card)
-{
- mutex_lock(&card->power_lock);
-}
-
-static inline void snd_power_unlock(struct snd_card *card)
-{
- mutex_unlock(&card->power_lock);
-}
-
static inline unsigned int snd_power_get_state(struct snd_card *card)
{
return card->power_state;
#else /* ! CONFIG_PM */
-#define snd_power_lock(card) do { (void)(card); } while (0)
-#define snd_power_unlock(card) do { (void)(card); } while (0)
static inline int snd_power_wait(struct snd_card *card, unsigned int state) { return 0; }
#define snd_power_get_state(card) ({ (void)(card); SNDRV_CTL_POWER_D0; })
#define snd_power_change_state(card, state) do { (void)(card); } while (0)
if (copy_from_user(&info, _info, sizeof(info)))
return -EFAULT;
- snd_power_lock(ctl->card);
result = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0);
- if (result >= 0)
- result = snd_ctl_elem_info(ctl, &info);
- snd_power_unlock(ctl->card);
- if (result >= 0)
- if (copy_to_user(_info, &info, sizeof(info)))
- return -EFAULT;
+ if (result < 0)
+ return result;
+ result = snd_ctl_elem_info(ctl, &info);
+ if (result < 0)
+ return result;
+ if (copy_to_user(_info, &info, sizeof(info)))
+ return -EFAULT;
return result;
}
if (IS_ERR(control))
return PTR_ERR(control);
- snd_power_lock(card);
result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
- if (result >= 0) {
- down_read(&card->controls_rwsem);
- result = snd_ctl_elem_read(card, control);
- up_read(&card->controls_rwsem);
- }
- snd_power_unlock(card);
- if (result >= 0)
- if (copy_to_user(_control, control, sizeof(*control)))
- result = -EFAULT;
+ if (result < 0)
+ goto error;
+
+ down_read(&card->controls_rwsem);
+ result = snd_ctl_elem_read(card, control);
+ up_read(&card->controls_rwsem);
+ if (result < 0)
+ goto error;
+
+ if (copy_to_user(_control, control, sizeof(*control)))
+ result = -EFAULT;
+ error:
kfree(control);
return result;
}
return PTR_ERR(control);
card = file->card;
- snd_power_lock(card);
result = snd_power_wait(card, SNDRV_CTL_POWER_D0);
- if (result >= 0) {
- down_write(&card->controls_rwsem);
- result = snd_ctl_elem_write(card, file, control);
- up_write(&card->controls_rwsem);
- }
- snd_power_unlock(card);
- if (result >= 0)
- if (copy_to_user(_control, control, sizeof(*control)))
- result = -EFAULT;
+ if (result < 0)
+ goto error;
+
+ down_write(&card->controls_rwsem);
+ result = snd_ctl_elem_write(card, file, control);
+ up_write(&card->controls_rwsem);
+ if (result < 0)
+ goto error;
+
+ if (copy_to_user(_control, control, sizeof(*control)))
+ result = -EFAULT;
+ error:
kfree(control);
return result;
}
if (get_user(data->value.enumerated.item, &data32->value.enumerated.item))
goto error;
- snd_power_lock(ctl->card);
err = snd_power_wait(ctl->card, SNDRV_CTL_POWER_D0);
- if (err >= 0)
- err = snd_ctl_elem_info(ctl, data);
- snd_power_unlock(ctl->card);
-
+ if (err < 0)
+ goto error;
+ err = snd_ctl_elem_info(ctl, data);
if (err < 0)
goto error;
/* restore info to 32bit */
if (err < 0)
goto error;
- snd_power_lock(card);
err = snd_power_wait(card, SNDRV_CTL_POWER_D0);
- if (err >= 0)
- err = snd_ctl_elem_read(card, data);
- snd_power_unlock(card);
- if (err >= 0)
- err = copy_ctl_value_to_user(userdata, valuep, data,
- type, count);
+ if (err < 0)
+ goto error;
+ err = snd_ctl_elem_read(card, data);
+ if (err < 0)
+ goto error;
+ err = copy_ctl_value_to_user(userdata, valuep, data, type, count);
error:
kfree(data);
return err;
if (err < 0)
goto error;
- snd_power_lock(card);
err = snd_power_wait(card, SNDRV_CTL_POWER_D0);
- if (err >= 0)
- err = snd_ctl_elem_write(card, file, data);
- snd_power_unlock(card);
- if (err >= 0)
- err = copy_ctl_value_to_user(userdata, valuep, data,
- type, count);
+ if (err < 0)
+ goto error;
+ err = snd_ctl_elem_write(card, file, data);
+ if (err < 0)
+ goto error;
+ err = copy_ctl_value_to_user(userdata, valuep, data, type, count);
error:
kfree(data);
return err;
spin_lock_init(&card->files_lock);
INIT_LIST_HEAD(&card->files_list);
#ifdef CONFIG_PM
- mutex_init(&card->power_lock);
init_waitqueue_head(&card->power_sleep);
#endif
* Waits until the power-state is changed.
*
* Return: Zero if successful, or a negative error code.
- *
- * Note: the power lock must be active before call.
*/
int snd_power_wait(struct snd_card *card, unsigned int power_state)
{
if (snd_power_get_state(card) == power_state)
break;
set_current_state(TASK_UNINTERRUPTIBLE);
- snd_power_unlock(card);
schedule_timeout(30 * HZ);
- snd_power_lock(card);
}
remove_wait_queue(&card->power_sleep, &wait);
return result;
add_wait_queue(&to_check->sleep, &wait);
snd_pcm_stream_unlock_irq(substream);
up_read(&snd_pcm_link_rwsem);
- snd_power_unlock(card);
if (runtime->no_period_wakeup)
tout = MAX_SCHEDULE_TIMEOUT;
else {
tout = msecs_to_jiffies(tout * 1000);
}
tout = schedule_timeout_interruptible(tout);
- snd_power_lock(card);
down_read(&snd_pcm_link_rwsem);
snd_pcm_stream_lock_irq(substream);
remove_wait_queue(&to_check->sleep, &wait);
return 0;
}
-static int snd_pcm_common_ioctl(struct file *file,
+static int snd_pcm_common_ioctl1(struct file *file,
struct snd_pcm_substream *substream,
unsigned int cmd, void __user *arg)
{
struct snd_pcm_file *pcm_file = file->private_data;
+ int res;
+
+ res = snd_power_wait(substream->pcm->card, SNDRV_CTL_POWER_D0);
+ if (res < 0)
+ return res;
switch (cmd) {
case SNDRV_PCM_IOCTL_PVERSION:
return -ENOTTY;
}
-static int snd_pcm_common_ioctl1(struct file *file,
- struct snd_pcm_substream *substream,
- unsigned int cmd, void __user *arg)
-{
- struct snd_card *card = substream->pcm->card;
- int res;
-
- snd_power_lock(card);
- res = snd_power_wait(card, SNDRV_CTL_POWER_D0);
- if (res >= 0)
- res = snd_pcm_common_ioctl(file, substream, cmd, arg);
- snd_power_unlock(card);
- return res;
-}
-
static int snd_pcm_playback_ioctl1(struct file *file,
struct snd_pcm_substream *substream,
unsigned int cmd, void __user *arg)
{
snd_pcm_uframes_t *frames = arg;
snd_pcm_sframes_t result;
- int err;
switch (cmd) {
case SNDRV_PCM_IOCTL_FORWARD:
case SNDRV_PCM_IOCTL_START:
return snd_pcm_start_lock_irq(substream);
case SNDRV_PCM_IOCTL_DRAIN:
- snd_power_lock(substream->pcm->card);
- err = snd_pcm_drain(substream, NULL);
- snd_power_unlock(substream->pcm->card);
- return err;
+ return snd_pcm_drain(substream, NULL);
case SNDRV_PCM_IOCTL_DROP:
return snd_pcm_drop(substream);
case SNDRV_PCM_IOCTL_DELAY:
/* Due to the resume being scheduled into a workqueue we could
* suspend before that's finished - wait for it to complete.
*/
- snd_power_lock(card->snd_card);
snd_power_wait(card->snd_card, SNDRV_CTL_POWER_D0);
- snd_power_unlock(card->snd_card);
/* we're going to block userspace touching us until resume completes */
snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D3hot);