diff options
Diffstat (limited to 'sound/core/pcm_native.c')
| -rw-r--r-- | sound/core/pcm_native.c | 35 | 
1 files changed, 29 insertions, 6 deletions
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 5e12e5bacbb..f9ddecf2f4c 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -369,6 +369,14 @@ static int period_to_usecs(struct snd_pcm_runtime *runtime)  	return usecs;  } +static void snd_pcm_set_state(struct snd_pcm_substream *substream, int state) +{ +	snd_pcm_stream_lock_irq(substream); +	if (substream->runtime->status->state != SNDRV_PCM_STATE_DISCONNECTED) +		substream->runtime->status->state = state; +	snd_pcm_stream_unlock_irq(substream); +} +  static int snd_pcm_hw_params(struct snd_pcm_substream *substream,  			     struct snd_pcm_hw_params *params)  { @@ -452,7 +460,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,  		runtime->boundary *= 2;  	snd_pcm_timer_resolution_change(substream); -	runtime->status->state = SNDRV_PCM_STATE_SETUP; +	snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP);  	if (pm_qos_request_active(&substream->latency_pm_qos_req))  		pm_qos_remove_request(&substream->latency_pm_qos_req); @@ -464,7 +472,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,  	/* hardware might be unusable from this time,  	   so we force application to retry to set  	   the correct hardware parameter settings */ -	runtime->status->state = SNDRV_PCM_STATE_OPEN; +	snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);  	if (substream->ops->hw_free != NULL)  		substream->ops->hw_free(substream);  	return err; @@ -512,7 +520,7 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream)  		return -EBADFD;  	if (substream->ops->hw_free)  		result = substream->ops->hw_free(substream); -	runtime->status->state = SNDRV_PCM_STATE_OPEN; +	snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);  	pm_qos_remove_request(&substream->latency_pm_qos_req);  	return result;  } @@ -1320,7 +1328,7 @@ static void snd_pcm_post_prepare(struct snd_pcm_substream *substream, int state)  {  	struct snd_pcm_runtime *runtime = substream->runtime;  	runtime->control->appl_ptr = runtime->status->hw_ptr; -	runtime->status->state = SNDRV_PCM_STATE_PREPARED; +	snd_pcm_set_state(substream, SNDRV_PCM_STATE_PREPARED);  }  static struct action_ops snd_pcm_action_prepare = { @@ -1510,6 +1518,10 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,  		down_read(&snd_pcm_link_rwsem);  		snd_pcm_stream_lock_irq(substream);  		remove_wait_queue(&to_check->sleep, &wait); +		if (card->shutdown) { +			result = -ENODEV; +			break; +		}  		if (tout == 0) {  			if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)  				result = -ESTRPIPE; @@ -1634,6 +1646,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)  	write_unlock_irq(&snd_pcm_link_rwlock);  	up_write(&snd_pcm_link_rwsem);   _nolock: +	snd_card_unref(substream1->pcm->card);  	fput_light(file, fput_needed);  	if (res < 0)  		kfree(group); @@ -2108,7 +2121,10 @@ static int snd_pcm_playback_open(struct inode *inode, struct file *file)  		return err;  	pcm = snd_lookup_minor_data(iminor(inode),  				    SNDRV_DEVICE_TYPE_PCM_PLAYBACK); -	return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK); +	err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK); +	if (pcm) +		snd_card_unref(pcm->card); +	return err;  }  static int snd_pcm_capture_open(struct inode *inode, struct file *file) @@ -2119,7 +2135,10 @@ static int snd_pcm_capture_open(struct inode *inode, struct file *file)  		return err;  	pcm = snd_lookup_minor_data(iminor(inode),  				    SNDRV_DEVICE_TYPE_PCM_CAPTURE); -	return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE); +	err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE); +	if (pcm) +		snd_card_unref(pcm->card); +	return err;  }  static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) @@ -2156,6 +2175,10 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)  		mutex_unlock(&pcm->open_mutex);  		schedule();  		mutex_lock(&pcm->open_mutex); +		if (pcm->card->shutdown) { +			err = -ENODEV; +			break; +		}  		if (signal_pending(current)) {  			err = -ERESTARTSYS;  			break;  |