diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-11 09:19:35 -0700 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-11 09:19:35 -0700 | 
| commit | a9c86d42599519f3d83b5f46bdab25046fe47b84 (patch) | |
| tree | 9b269e3162e5cc0c1a8dfc3349303c902718a9a9 /sound/core/pcm_native.c | |
| parent | a12e4d304ce701844c639541d90df86e165d03f9 (diff) | |
| parent | 1110afbe728838ac7ce973c37af9e11385dbaef9 (diff) | |
| download | olio-linux-3.10-a9c86d42599519f3d83b5f46bdab25046fe47b84.tar.xz olio-linux-3.10-a9c86d42599519f3d83b5f46bdab25046fe47b84.zip  | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6: (377 commits)
  ASoC: au1x: PSC-AC97 bugfixes
  ALSA: dummy - Increase MAX_PCM_SUBSTREAMS to 128
  ALSA: dummy - Add debug proc file
  ALSA: Add const prefix to proc helper functions
  ALSA: Re-export snd_pcm_format_name() function
  ALSA: hda - Use auto model for HP laptops with ALC268 codec
  ALSA: cs46xx - Fix minimum period size
  ASoC: Fix WM835x Out4 capture enumeration
  ALSA: Remove unneeded ifdef from sound/core.h
  ALSA: Remove struct snd_monitor_file from public sound/core.h
  ASoC: Remove unuused hw_read_t
  sound: oxygen: work around MCE when changing volume
  ALSA: dummy - Fake buffer allocations
  ALSA: hda/realtek: Added support for CLEVO M540R subsystem, 6 channel + digital
  ASoC: fix pxa2xx-ac97.c breakage
  ALSA: dummy - Fix the timer calculation in systimer mode
  ALSA: dummy - Add more description
  ALSA: dummy - Better jiffies handling
  ALSA: dummy - Support high-res timer mode
  ALSA: Release v1.0.21
  ...
Diffstat (limited to 'sound/core/pcm_native.c')
| -rw-r--r-- | sound/core/pcm_native.c | 64 | 
1 files changed, 41 insertions, 23 deletions
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index ac2150e0670..59e5fbe6af5 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -1343,8 +1343,6 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream,  static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state)  { -	if (substream->f_flags & O_NONBLOCK) -		return -EAGAIN;  	substream->runtime->trigger_master = substream;  	return 0;  } @@ -1392,7 +1390,6 @@ static struct action_ops snd_pcm_action_drain_init = {  struct drain_rec {  	struct snd_pcm_substream *substream;  	wait_queue_t wait; -	snd_pcm_uframes_t stop_threshold;  };  static int snd_pcm_drop(struct snd_pcm_substream *substream); @@ -1404,13 +1401,15 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream);   * After this call, all streams are supposed to be either SETUP or DRAINING   * (capture only) state.   */ -static int snd_pcm_drain(struct snd_pcm_substream *substream) +static int snd_pcm_drain(struct snd_pcm_substream *substream, +			 struct file *file)  {  	struct snd_card *card;  	struct snd_pcm_runtime *runtime;  	struct snd_pcm_substream *s;  	int result = 0;  	int i, num_drecs; +	int nonblock = 0;  	struct drain_rec *drec, drec_tmp, *d;  	card = substream->pcm->card; @@ -1428,6 +1427,15 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream)  		}  	} +	if (file) { +		if (file->f_flags & O_NONBLOCK) +			nonblock = 1; +	} else if (substream->f_flags & O_NONBLOCK) +		nonblock = 1; + +	if (nonblock) +		goto lock; /* no need to allocate waitqueues */ +  	/* allocate temporary record for drain sync */  	down_read(&snd_pcm_link_rwsem);  	if (snd_pcm_stream_linked(substream)) { @@ -1449,16 +1457,11 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream)  			d->substream = s;  			init_waitqueue_entry(&d->wait, current);  			add_wait_queue(&runtime->sleep, &d->wait); -			/* stop_threshold fixup to avoid endless loop when -			 * stop_threshold > buffer_size -			 */ -			d->stop_threshold = runtime->stop_threshold; -			if (runtime->stop_threshold > runtime->buffer_size) -				runtime->stop_threshold = runtime->buffer_size;  		}  	}  	up_read(&snd_pcm_link_rwsem); + lock:  	snd_pcm_stream_lock_irq(substream);  	/* resume pause */  	if (substream->runtime->status->state == SNDRV_PCM_STATE_PAUSED) @@ -1466,9 +1469,12 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream)  	/* pre-start/stop - all running streams are changed to DRAINING state */  	result = snd_pcm_action(&snd_pcm_action_drain_init, substream, 0); -	if (result < 0) { -		snd_pcm_stream_unlock_irq(substream); -		goto _error; +	if (result < 0) +		goto unlock; +	/* in non-blocking, we don't wait in ioctl but let caller poll */ +	if (nonblock) { +		result = -EAGAIN; +		goto unlock;  	}  	for (;;) { @@ -1504,18 +1510,18 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream)  		}  	} + unlock:  	snd_pcm_stream_unlock_irq(substream); - _error: -	for (i = 0; i < num_drecs; i++) { -		d = &drec[i]; -		runtime = d->substream->runtime; -		remove_wait_queue(&runtime->sleep, &d->wait); -		runtime->stop_threshold = d->stop_threshold; +	if (!nonblock) { +		for (i = 0; i < num_drecs; i++) { +			d = &drec[i]; +			runtime = d->substream->runtime; +			remove_wait_queue(&runtime->sleep, &d->wait); +		} +		if (drec != &drec_tmp) +			kfree(drec);  	} - -	if (drec != &drec_tmp) -		kfree(drec);  	snd_power_unlock(card);  	return result; @@ -2208,6 +2214,9 @@ static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *subst  	case SNDRV_PCM_STATE_XRUN:  		ret = -EPIPE;  		goto __end; +	case SNDRV_PCM_STATE_SUSPENDED: +		ret = -ESTRPIPE; +		goto __end;  	default:  		ret = -EBADFD;  		goto __end; @@ -2253,6 +2262,9 @@ static snd_pcm_sframes_t snd_pcm_capture_rewind(struct snd_pcm_substream *substr  	case SNDRV_PCM_STATE_XRUN:  		ret = -EPIPE;  		goto __end; +	case SNDRV_PCM_STATE_SUSPENDED: +		ret = -ESTRPIPE; +		goto __end;  	default:  		ret = -EBADFD;  		goto __end; @@ -2299,6 +2311,9 @@ static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *subs  	case SNDRV_PCM_STATE_XRUN:  		ret = -EPIPE;  		goto __end; +	case SNDRV_PCM_STATE_SUSPENDED: +		ret = -ESTRPIPE; +		goto __end;  	default:  		ret = -EBADFD;  		goto __end; @@ -2345,6 +2360,9 @@ static snd_pcm_sframes_t snd_pcm_capture_forward(struct snd_pcm_substream *subst  	case SNDRV_PCM_STATE_XRUN:  		ret = -EPIPE;  		goto __end; +	case SNDRV_PCM_STATE_SUSPENDED: +		ret = -ESTRPIPE; +		goto __end;  	default:  		ret = -EBADFD;  		goto __end; @@ -2544,7 +2562,7 @@ static int snd_pcm_common_ioctl1(struct file *file,  		return snd_pcm_hw_params_old_user(substream, arg);  #endif  	case SNDRV_PCM_IOCTL_DRAIN: -		return snd_pcm_drain(substream); +		return snd_pcm_drain(substream, file);  	case SNDRV_PCM_IOCTL_DROP:  		return snd_pcm_drop(substream);  	case SNDRV_PCM_IOCTL_PAUSE:  |