Commit 650224fe authored by Takashi Iwai's avatar Takashi Iwai
Browse files

ALSA: pcm: Use guard() for PCM stream locks



Define guard() usage for PCM stream locking and use it in appropriate
places.

The pair of snd_pcm_stream_lock() and snd_pcm_stream_unlock() can be
presented with guard(pcm_stream_lock) now.

Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
Link: https://lore.kernel.org/r/20240227085306.9764-23-tiwai@suse.de
parent dd0da75b
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -659,6 +659,18 @@ void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream,
		flags = _snd_pcm_stream_lock_irqsave_nested(substream); \
	} while (0)

/* definitions for guard(); use like guard(pcm_stream_lock) */
DEFINE_LOCK_GUARD_1(pcm_stream_lock, struct snd_pcm_substream,
		    snd_pcm_stream_lock(_T->lock),
		    snd_pcm_stream_unlock(_T->lock))
DEFINE_LOCK_GUARD_1(pcm_stream_lock_irq, struct snd_pcm_substream,
		    snd_pcm_stream_lock_irq(_T->lock),
		    snd_pcm_stream_unlock_irq(_T->lock))
DEFINE_LOCK_GUARD_1(pcm_stream_lock_irqsave, struct snd_pcm_substream,
		    snd_pcm_stream_lock_irqsave(_T->lock, _T->flags),
		    snd_pcm_stream_unlock_irqrestore(_T->lock, _T->flags),
		    unsigned long flags)

/**
 * snd_pcm_group_for_each_entry - iterate over the linked substreams
 * @s: the iterator
+14 −15
Original line number Diff line number Diff line
@@ -1623,9 +1623,8 @@ static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size)
			break;
		result = 0;
		set_current_state(TASK_INTERRUPTIBLE);
		snd_pcm_stream_lock_irq(substream);
		scoped_guard(pcm_stream_lock_irq, substream)
			state = runtime->state;
		snd_pcm_stream_unlock_irq(substream);
		if (state != SNDRV_PCM_STATE_RUNNING) {
			set_current_state(TASK_RUNNING);
			break;
@@ -2840,23 +2839,23 @@ static __poll_t snd_pcm_oss_poll(struct file *file, poll_table * wait)
	if (psubstream != NULL) {
		struct snd_pcm_runtime *runtime = psubstream->runtime;
		poll_wait(file, &runtime->sleep, wait);
		snd_pcm_stream_lock_irq(psubstream);
		scoped_guard(pcm_stream_lock_irq, psubstream) {
			if (runtime->state != SNDRV_PCM_STATE_DRAINING &&
			    (runtime->state != SNDRV_PCM_STATE_RUNNING ||
			     snd_pcm_oss_playback_ready(psubstream)))
				mask |= EPOLLOUT | EPOLLWRNORM;
		snd_pcm_stream_unlock_irq(psubstream);
		}
	}
	if (csubstream != NULL) {
		struct snd_pcm_runtime *runtime = csubstream->runtime;
		snd_pcm_state_t ostate;
		poll_wait(file, &runtime->sleep, wait);
		snd_pcm_stream_lock_irq(csubstream);
		scoped_guard(pcm_stream_lock_irq, csubstream) {
			ostate = runtime->state;
			if (ostate != SNDRV_PCM_STATE_RUNNING ||
			    snd_pcm_oss_capture_ready(csubstream))
				mask |= EPOLLIN | EPOLLRDNORM;
		snd_pcm_stream_unlock_irq(csubstream);
		}
		if (ostate != SNDRV_PCM_STATE_RUNNING && runtime->oss.trigger) {
			struct snd_pcm_oss_file ofile;
			memset(&ofile, 0, sizeof(ofile));
+32 −34
Original line number Diff line number Diff line
@@ -432,7 +432,7 @@ static int snd_pcm_ioctl_sync_ptr_x32(struct snd_pcm_substream *substream,
	boundary = recalculate_boundary(runtime);
	if (!boundary)
		boundary = 0x7fffffff;
	snd_pcm_stream_lock_irq(substream);
	scoped_guard(pcm_stream_lock_irq, substream) {
		/* FIXME: we should consider the boundary for the sync from app */
		if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL))
			control->appl_ptr = scontrol.appl_ptr;
@@ -447,7 +447,7 @@ static int snd_pcm_ioctl_sync_ptr_x32(struct snd_pcm_substream *substream,
		sstatus.tstamp = status->tstamp;
		sstatus.suspended_state = status->suspended_state;
		sstatus.audio_tstamp = status->audio_tstamp;
	snd_pcm_stream_unlock_irq(substream);
	}
	if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL))
		snd_pcm_dma_buffer_sync(substream, SNDRV_DMA_SYNC_DEVICE);
	if (put_user(sstatus.state, &src->s.status.state) ||
@@ -510,13 +510,11 @@ static int snd_pcm_ioctl_sync_ptr_buggy(struct snd_pcm_substream *substream,
		if (err < 0)
			return err;
	}
	snd_pcm_stream_lock_irq(substream);
	scoped_guard(pcm_stream_lock_irq, substream) {
		if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL)) {
			err = pcm_lib_apply_appl_ptr(substream, sync_cp->appl_ptr);
		if (err < 0) {
			snd_pcm_stream_unlock_irq(substream);
			if (err < 0)
				return err;
		}
		} else {
			sync_cp->appl_ptr = control->appl_ptr;
		}
@@ -529,7 +527,7 @@ static int snd_pcm_ioctl_sync_ptr_buggy(struct snd_pcm_substream *substream,
		sync_ptr.s.status.tstamp = status->tstamp;
		sync_ptr.s.status.suspended_state = status->suspended_state;
		sync_ptr.s.status.audio_tstamp = status->audio_tstamp;
	snd_pcm_stream_unlock_irq(substream);
	}
	if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL))
		snd_pcm_dma_buffer_sync(substream, SNDRV_DMA_SYNC_DEVICE);
	if (copy_to_user(_sync_ptr, &sync_ptr, sizeof(sync_ptr)))
+3 −7
Original line number Diff line number Diff line
@@ -1744,8 +1744,8 @@ static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream,
				   void *arg)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	unsigned long flags;
	snd_pcm_stream_lock_irqsave(substream, flags);

	guard(pcm_stream_lock_irqsave)(substream);
	if (snd_pcm_running(substream) &&
	    snd_pcm_update_hw_ptr(substream) >= 0)
		runtime->status->hw_ptr %= runtime->buffer_size;
@@ -1753,7 +1753,6 @@ static int snd_pcm_lib_ioctl_reset(struct snd_pcm_substream *substream,
		runtime->status->hw_ptr = 0;
		runtime->hw_ptr_wrap = 0;
	}
	snd_pcm_stream_unlock_irqrestore(substream, flags);
	return 0;
}

@@ -1899,14 +1898,11 @@ EXPORT_SYMBOL(snd_pcm_period_elapsed_under_stream_lock);
 */
void snd_pcm_period_elapsed(struct snd_pcm_substream *substream)
{
	unsigned long flags;

	if (snd_BUG_ON(!substream))
		return;

	snd_pcm_stream_lock_irqsave(substream, flags);
	guard(pcm_stream_lock_irqsave)(substream);
	snd_pcm_period_elapsed_under_stream_lock(substream);
	snd_pcm_stream_unlock_irqrestore(substream, flags);
}
EXPORT_SYMBOL(snd_pcm_period_elapsed);

+130 −162
Original line number Diff line number Diff line
@@ -604,10 +604,9 @@ static int period_to_usecs(struct snd_pcm_runtime *runtime)
static void snd_pcm_set_state(struct snd_pcm_substream *substream,
			      snd_pcm_state_t state)
{
	snd_pcm_stream_lock_irq(substream);
	guard(pcm_stream_lock_irq)(substream);
	if (substream->runtime->state != SNDRV_PCM_STATE_DISCONNECTED)
		__snd_pcm_set_state(substream->runtime, state);
	snd_pcm_stream_unlock_irq(substream);
}

static inline void snd_pcm_timer_notify(struct snd_pcm_substream *substream,
@@ -733,7 +732,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
	err = snd_pcm_buffer_access_lock(runtime);
	if (err < 0)
		return err;
	snd_pcm_stream_lock_irq(substream);
	scoped_guard(pcm_stream_lock_irq, substream) {
		switch (runtime->state) {
		case SNDRV_PCM_STATE_OPEN:
		case SNDRV_PCM_STATE_SETUP:
@@ -746,7 +745,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
			err = -EBADFD;
			break;
		}
	snd_pcm_stream_unlock_irq(substream);
	}
	if (err)
		goto unlock;

@@ -896,7 +895,7 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
	result = snd_pcm_buffer_access_lock(runtime);
	if (result < 0)
		return result;
	snd_pcm_stream_lock_irq(substream);
	scoped_guard(pcm_stream_lock_irq, substream) {
		switch (runtime->state) {
		case SNDRV_PCM_STATE_SETUP:
		case SNDRV_PCM_STATE_PREPARED:
@@ -907,7 +906,7 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
			result = -EBADFD;
			break;
		}
	snd_pcm_stream_unlock_irq(substream);
	}
	if (result)
		goto unlock;
	result = do_hw_free(substream);
@@ -927,12 +926,10 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream,
	if (PCM_RUNTIME_CHECK(substream))
		return -ENXIO;
	runtime = substream->runtime;
	snd_pcm_stream_lock_irq(substream);
	if (runtime->state == SNDRV_PCM_STATE_OPEN) {
		snd_pcm_stream_unlock_irq(substream);
	scoped_guard(pcm_stream_lock_irq, substream) {
		if (runtime->state == SNDRV_PCM_STATE_OPEN)
			return -EBADFD;
	}
	snd_pcm_stream_unlock_irq(substream);

	if (params->tstamp_mode < 0 ||
	    params->tstamp_mode > SNDRV_PCM_TSTAMP_LAST)
@@ -952,7 +949,7 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream,
			return -EINVAL;
	}
	err = 0;
	snd_pcm_stream_lock_irq(substream);
	scoped_guard(pcm_stream_lock_irq, substream) {
		runtime->tstamp_mode = params->tstamp_mode;
		if (params->proto >= SNDRV_PROTOCOL_VERSION(2, 0, 12))
			runtime->tstamp_type = params->tstamp_type;
@@ -969,7 +966,7 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream,
				snd_pcm_playback_silence(substream, ULONG_MAX);
			err = snd_pcm_update_state(substream, runtime);
		}
	snd_pcm_stream_unlock_irq(substream);
	}
	return err;
}

@@ -1003,7 +1000,7 @@ int snd_pcm_status64(struct snd_pcm_substream *substream,
{
	struct snd_pcm_runtime *runtime = substream->runtime;

	snd_pcm_stream_lock_irq(substream);
	guard(pcm_stream_lock_irq)(substream);

	snd_pcm_unpack_audio_tstamp_config(status->audio_tstamp_data,
					&runtime->audio_tstamp_config);
@@ -1024,7 +1021,7 @@ int snd_pcm_status64(struct snd_pcm_substream *substream,
	status->state = runtime->state;
	status->suspended_state = runtime->suspended_state;
	if (status->state == SNDRV_PCM_STATE_OPEN)
		goto _end;
		return 0;
	status->trigger_tstamp_sec = runtime->trigger_tstamp.tv_sec;
	status->trigger_tstamp_nsec = runtime->trigger_tstamp.tv_nsec;
	if (snd_pcm_running(substream)) {
@@ -1069,8 +1066,6 @@ int snd_pcm_status64(struct snd_pcm_substream *substream,
	status->overrange = runtime->overrange;
	runtime->avail_max = 0;
	runtime->overrange = 0;
 _end:
 	snd_pcm_stream_unlock_irq(substream);
	return 0;
}

@@ -1155,12 +1150,10 @@ static int snd_pcm_channel_info(struct snd_pcm_substream *substream,
	
	channel = info->channel;
	runtime = substream->runtime;
	snd_pcm_stream_lock_irq(substream);
	if (runtime->state == SNDRV_PCM_STATE_OPEN) {
		snd_pcm_stream_unlock_irq(substream);
	scoped_guard(pcm_stream_lock_irq, substream) {
		if (runtime->state == SNDRV_PCM_STATE_OPEN)
			return -EBADFD;
	}
	snd_pcm_stream_unlock_irq(substream);
	if (channel >= runtime->channels)
		return -EINVAL;
	memset(info, 0, sizeof(*info));
@@ -1381,12 +1374,8 @@ static int snd_pcm_action_lock_irq(const struct action_ops *ops,
				   struct snd_pcm_substream *substream,
				   snd_pcm_state_t state)
{
	int res;

	snd_pcm_stream_lock_irq(substream);
	res = snd_pcm_action(ops, substream, state);
	snd_pcm_stream_unlock_irq(substream);
	return res;
	guard(pcm_stream_lock_irq)(substream);
	return snd_pcm_action(ops, substream, state);
}

/*
@@ -1576,12 +1565,9 @@ int snd_pcm_drain_done(struct snd_pcm_substream *substream)
 */
int snd_pcm_stop_xrun(struct snd_pcm_substream *substream)
{
	unsigned long flags;

	snd_pcm_stream_lock_irqsave(substream, flags);
	guard(pcm_stream_lock_irqsave)(substream);
	if (substream->runtime && snd_pcm_running(substream))
		__snd_pcm_xrun(substream);
	snd_pcm_stream_unlock_irqrestore(substream, flags);
	return 0;
}
EXPORT_SYMBOL_GPL(snd_pcm_stop_xrun);
@@ -1733,14 +1719,9 @@ static const struct action_ops snd_pcm_action_suspend = {
 */
static int snd_pcm_suspend(struct snd_pcm_substream *substream)
{
	int err;
	unsigned long flags;

	snd_pcm_stream_lock_irqsave(substream, flags);
	err = snd_pcm_action(&snd_pcm_action_suspend, substream,
	guard(pcm_stream_lock_irqsave)(substream);
	return snd_pcm_action(&snd_pcm_action_suspend, substream,
			      ACTION_ARG_IGNORE);
	snd_pcm_stream_unlock_irqrestore(substream, flags);
	return err;
}

/**
@@ -1856,22 +1837,17 @@ static int snd_pcm_resume(struct snd_pcm_substream *substream)
static int snd_pcm_xrun(struct snd_pcm_substream *substream)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	int result;

	snd_pcm_stream_lock_irq(substream);
	guard(pcm_stream_lock_irq)(substream);
	switch (runtime->state) {
	case SNDRV_PCM_STATE_XRUN:
		result = 0;	/* already there */
		break;
		return 0;	/* already there */
	case SNDRV_PCM_STATE_RUNNING:
		__snd_pcm_xrun(substream);
		result = 0;
		break;
		return 0;
	default:
		result = -EBADFD;
		return -EBADFD;
	}
	snd_pcm_stream_unlock_irq(substream);
	return result;
}

/*
@@ -1900,13 +1876,12 @@ static int snd_pcm_do_reset(struct snd_pcm_substream *substream,
	int err = snd_pcm_ops_ioctl(substream, SNDRV_PCM_IOCTL1_RESET, NULL);
	if (err < 0)
		return err;
	snd_pcm_stream_lock_irq(substream);
	guard(pcm_stream_lock_irq)(substream);
	runtime->hw_ptr_base = 0;
	runtime->hw_ptr_interrupt = runtime->status->hw_ptr -
		runtime->status->hw_ptr % runtime->period_size;
	runtime->silence_start = runtime->status->hw_ptr;
	runtime->silence_filled = 0;
	snd_pcm_stream_unlock_irq(substream);
	return 0;
}

@@ -1914,12 +1889,11 @@ static void snd_pcm_post_reset(struct snd_pcm_substream *substream,
			       snd_pcm_state_t state)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	snd_pcm_stream_lock_irq(substream);
	guard(pcm_stream_lock_irq)(substream);
	runtime->control->appl_ptr = runtime->status->hw_ptr;
	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
	    runtime->silence_size > 0)
		snd_pcm_playback_silence(substream, ULONG_MAX);
	snd_pcm_stream_unlock_irq(substream);
}

static const struct action_ops snd_pcm_action_reset = {
@@ -1995,7 +1969,7 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream,
	else
		f_flags = substream->f_flags;

	snd_pcm_stream_lock_irq(substream);
	scoped_guard(pcm_stream_lock_irq, substream) {
		switch (substream->runtime->state) {
		case SNDRV_PCM_STATE_PAUSED:
			snd_pcm_pause(substream, false);
@@ -2004,7 +1978,7 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream,
			snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
			break;
		}
	snd_pcm_stream_unlock_irq(substream);
	}

	return snd_pcm_action_nonatomic(&snd_pcm_action_prepare,
					substream,
@@ -2221,14 +2195,13 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream)
	    runtime->state == SNDRV_PCM_STATE_DISCONNECTED)
		return -EBADFD;

	snd_pcm_stream_lock_irq(substream);
	guard(pcm_stream_lock_irq)(substream);
	/* resume pause */
	if (runtime->state == SNDRV_PCM_STATE_PAUSED)
		snd_pcm_pause(substream, false);

	snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
	/* runtime->control->appl_ptr = runtime->status->hw_ptr; */
	snd_pcm_stream_unlock_irq(substream);

	return result;
}
@@ -2288,13 +2261,13 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
	if (snd_pcm_stream_linked(substream1))
		return -EALREADY;

	snd_pcm_stream_lock_irq(substream);
	scoped_guard(pcm_stream_lock_irq, substream) {
		if (!snd_pcm_stream_linked(substream)) {
			snd_pcm_group_assign(substream, group);
			group = NULL; /* assigned, don't free this one below */
		}
		target_group = substream->group;
	snd_pcm_stream_unlock_irq(substream);
	}

	snd_pcm_group_lock_irq(target_group, nonatomic);
	snd_pcm_stream_lock_nested(substream1);
@@ -3000,12 +2973,12 @@ static snd_pcm_sframes_t snd_pcm_rewind(struct snd_pcm_substream *substream,
	if (frames == 0)
		return 0;

	snd_pcm_stream_lock_irq(substream);
	scoped_guard(pcm_stream_lock_irq, substream) {
		ret = do_pcm_hwsync(substream);
		if (!ret)
			ret = rewind_appl_ptr(substream, frames,
					      snd_pcm_hw_avail(substream));
	snd_pcm_stream_unlock_irq(substream);
	}
	if (ret >= 0)
		snd_pcm_dma_buffer_sync(substream, SNDRV_DMA_SYNC_DEVICE);
	return ret;
@@ -3019,12 +2992,12 @@ static snd_pcm_sframes_t snd_pcm_forward(struct snd_pcm_substream *substream,
	if (frames == 0)
		return 0;

	snd_pcm_stream_lock_irq(substream);
	scoped_guard(pcm_stream_lock_irq, substream) {
		ret = do_pcm_hwsync(substream);
		if (!ret)
			ret = forward_appl_ptr(substream, frames,
					       snd_pcm_avail(substream));
	snd_pcm_stream_unlock_irq(substream);
	}
	if (ret >= 0)
		snd_pcm_dma_buffer_sync(substream, SNDRV_DMA_SYNC_DEVICE);
	return ret;
@@ -3035,11 +3008,11 @@ static int snd_pcm_delay(struct snd_pcm_substream *substream,
{
	int err;

	snd_pcm_stream_lock_irq(substream);
	scoped_guard(pcm_stream_lock_irq, substream) {
		err = do_pcm_hwsync(substream);
		if (delay && !err)
			*delay = snd_pcm_calc_delay(substream);
	snd_pcm_stream_unlock_irq(substream);
	}
	snd_pcm_dma_buffer_sync(substream, SNDRV_DMA_SYNC_CPU);

	return err;
@@ -3071,14 +3044,12 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
		if (err < 0)
			return err;
	}
	snd_pcm_stream_lock_irq(substream);
	scoped_guard(pcm_stream_lock_irq, substream) {
		if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL)) {
			err = pcm_lib_apply_appl_ptr(substream,
						     sync_ptr.c.control.appl_ptr);
		if (err < 0) {
			snd_pcm_stream_unlock_irq(substream);
			if (err < 0)
				return err;
		}
		} else {
			sync_ptr.c.control.appl_ptr = control->appl_ptr;
		}
@@ -3091,7 +3062,7 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
		sync_ptr.s.status.tstamp = status->tstamp;
		sync_ptr.s.status.suspended_state = status->suspended_state;
		sync_ptr.s.status.audio_tstamp = status->audio_tstamp;
	snd_pcm_stream_unlock_irq(substream);
	}
	if (!(sync_ptr.flags & SNDRV_PCM_SYNC_PTR_APPL))
		snd_pcm_dma_buffer_sync(substream, SNDRV_DMA_SYNC_DEVICE);
	if (copy_to_user(_sync_ptr, &sync_ptr, sizeof(sync_ptr)))
@@ -3169,15 +3140,13 @@ static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream,
	boundary = recalculate_boundary(runtime);
	if (! boundary)
		boundary = 0x7fffffff;
	snd_pcm_stream_lock_irq(substream);
	scoped_guard(pcm_stream_lock_irq, substream) {
		/* FIXME: we should consider the boundary for the sync from app */
		if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL)) {
			err = pcm_lib_apply_appl_ptr(substream,
						     scontrol.appl_ptr);
		if (err < 0) {
			snd_pcm_stream_unlock_irq(substream);
			if (err < 0)
				return err;
		}
		} else
			scontrol.appl_ptr = control->appl_ptr % boundary;
		if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
@@ -3189,7 +3158,7 @@ static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream,
		sstatus.tstamp = status->tstamp;
		sstatus.suspended_state = status->suspended_state;
		sstatus.audio_tstamp = status->audio_tstamp;
	snd_pcm_stream_unlock_irq(substream);
	}
	if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL))
		snd_pcm_dma_buffer_sync(substream, SNDRV_DMA_SYNC_DEVICE);
	if (put_user(sstatus.state, &src->s.status.state) ||
@@ -3628,7 +3597,7 @@ static __poll_t snd_pcm_poll(struct file *file, poll_table *wait)
	poll_wait(file, &runtime->sleep, wait);

	mask = 0;
	snd_pcm_stream_lock_irq(substream);
	guard(pcm_stream_lock_irq)(substream);
	avail = snd_pcm_avail(substream);
	switch (runtime->state) {
	case SNDRV_PCM_STATE_RUNNING:
@@ -3648,7 +3617,6 @@ static __poll_t snd_pcm_poll(struct file *file, poll_table *wait)
		mask = ok | EPOLLERR;
		break;
	}
	snd_pcm_stream_unlock_irq(substream);
	return mask;
}