Merge branch 'topic/pcm-estrpipe-in-pm' into for-linus
authorTakashi Iwai <tiwai@suse.de>
Thu, 10 Sep 2009 13:33:02 +0000 (15:33 +0200)
committerTakashi Iwai <tiwai@suse.de>
Thu, 10 Sep 2009 13:33:02 +0000 (15:33 +0200)
* topic/pcm-estrpipe-in-pm:
  ALSA: pcm - Tell user that stream to be rewound is suspended

1  2 
sound/core/pcm_native.c

diff --combined sound/core/pcm_native.c
@@@ -1343,6 -1343,8 +1343,6 @@@ static int snd_pcm_prepare(struct snd_p
  
  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;
  }
@@@ -1390,6 -1392,7 +1390,6 @@@ static struct action_ops snd_pcm_action
  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);
   * 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;
                }
        }
  
 +      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)) {
                        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)
  
        /* 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 (;;) {
                }
        }
  
 + 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;
@@@ -2214,6 -2208,9 +2214,9 @@@ static snd_pcm_sframes_t snd_pcm_playba
        case SNDRV_PCM_STATE_XRUN:
                ret = -EPIPE;
                goto __end;
+       case SNDRV_PCM_STATE_SUSPENDED:
+               ret = -ESTRPIPE;
+               goto __end;
        default:
                ret = -EBADFD;
                goto __end;
@@@ -2259,6 -2256,9 +2262,9 @@@ static snd_pcm_sframes_t snd_pcm_captur
        case SNDRV_PCM_STATE_XRUN:
                ret = -EPIPE;
                goto __end;
+       case SNDRV_PCM_STATE_SUSPENDED:
+               ret = -ESTRPIPE;
+               goto __end;
        default:
                ret = -EBADFD;
                goto __end;
@@@ -2305,6 -2305,9 +2311,9 @@@ static snd_pcm_sframes_t snd_pcm_playba
        case SNDRV_PCM_STATE_XRUN:
                ret = -EPIPE;
                goto __end;
+       case SNDRV_PCM_STATE_SUSPENDED:
+               ret = -ESTRPIPE;
+               goto __end;
        default:
                ret = -EBADFD;
                goto __end;
@@@ -2351,6 -2354,9 +2360,9 @@@ static snd_pcm_sframes_t snd_pcm_captur
        case SNDRV_PCM_STATE_XRUN:
                ret = -EPIPE;
                goto __end;
+       case SNDRV_PCM_STATE_SUSPENDED:
+               ret = -ESTRPIPE;
+               goto __end;
        default:
                ret = -EBADFD;
                goto __end;
@@@ -2550,7 -2556,7 +2562,7 @@@ static int snd_pcm_common_ioctl1(struc
                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: