diff options
| -rw-r--r-- | include/sound/pcm.h | 3 | ||||
| -rw-r--r-- | sound/core/pcm_lib.c | 30 | ||||
| -rw-r--r-- | sound/core/pcm_native.c | 6 |
3 files changed, 27 insertions, 12 deletions
diff --git a/include/sound/pcm.h b/include/sound/pcm.h index fe1b131842be..e26fb3c58037 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h | |||
| @@ -311,6 +311,7 @@ struct snd_pcm_runtime { | |||
| 311 | struct snd_pcm_mmap_control *control; | 311 | struct snd_pcm_mmap_control *control; |
| 312 | 312 | ||
| 313 | /* -- locking / scheduling -- */ | 313 | /* -- locking / scheduling -- */ |
| 314 | unsigned int nowake: 1; /* no wakeup (data-copy in progress) */ | ||
| 314 | wait_queue_head_t sleep; | 315 | wait_queue_head_t sleep; |
| 315 | struct fasync_struct *fasync; | 316 | struct fasync_struct *fasync; |
| 316 | 317 | ||
| @@ -839,6 +840,8 @@ void snd_pcm_set_sync(struct snd_pcm_substream *substream); | |||
| 839 | int snd_pcm_lib_interleave_len(struct snd_pcm_substream *substream); | 840 | int snd_pcm_lib_interleave_len(struct snd_pcm_substream *substream); |
| 840 | int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream, | 841 | int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream, |
| 841 | unsigned int cmd, void *arg); | 842 | unsigned int cmd, void *arg); |
| 843 | int snd_pcm_update_state(struct snd_pcm_substream *substream, | ||
| 844 | struct snd_pcm_runtime *runtime); | ||
| 842 | int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream); | 845 | int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream); |
| 843 | int snd_pcm_playback_xrun_check(struct snd_pcm_substream *substream); | 846 | int snd_pcm_playback_xrun_check(struct snd_pcm_substream *substream); |
| 844 | int snd_pcm_capture_xrun_check(struct snd_pcm_substream *substream); | 847 | int snd_pcm_capture_xrun_check(struct snd_pcm_substream *substream); |
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 70a4f7428d78..a63226232ef4 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
| @@ -263,8 +263,8 @@ static void xrun_log_show(struct snd_pcm_substream *substream) | |||
| 263 | 263 | ||
| 264 | #endif | 264 | #endif |
| 265 | 265 | ||
| 266 | static int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream, | 266 | int snd_pcm_update_state(struct snd_pcm_substream *substream, |
| 267 | struct snd_pcm_runtime *runtime) | 267 | struct snd_pcm_runtime *runtime) |
| 268 | { | 268 | { |
| 269 | snd_pcm_uframes_t avail; | 269 | snd_pcm_uframes_t avail; |
| 270 | 270 | ||
| @@ -285,7 +285,7 @@ static int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream, | |||
| 285 | return -EPIPE; | 285 | return -EPIPE; |
| 286 | } | 286 | } |
| 287 | } | 287 | } |
| 288 | if (avail >= runtime->control->avail_min) | 288 | if (!runtime->nowake && avail >= runtime->control->avail_min) |
| 289 | wake_up(&runtime->sleep); | 289 | wake_up(&runtime->sleep); |
| 290 | return 0; | 290 | return 0; |
| 291 | } | 291 | } |
| @@ -441,7 +441,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream, | |||
| 441 | if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) | 441 | if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) |
| 442 | snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp); | 442 | snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp); |
| 443 | 443 | ||
| 444 | return snd_pcm_update_hw_ptr_post(substream, runtime); | 444 | return snd_pcm_update_state(substream, runtime); |
| 445 | } | 445 | } |
| 446 | 446 | ||
| 447 | /* CAUTION: call it with irq disabled */ | 447 | /* CAUTION: call it with irq disabled */ |
| @@ -1792,6 +1792,7 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream, | |||
| 1792 | goto _end_unlock; | 1792 | goto _end_unlock; |
| 1793 | } | 1793 | } |
| 1794 | 1794 | ||
| 1795 | runtime->nowake = 1; | ||
| 1795 | while (size > 0) { | 1796 | while (size > 0) { |
| 1796 | snd_pcm_uframes_t frames, appl_ptr, appl_ofs; | 1797 | snd_pcm_uframes_t frames, appl_ptr, appl_ofs; |
| 1797 | snd_pcm_uframes_t avail; | 1798 | snd_pcm_uframes_t avail; |
| @@ -1813,15 +1814,17 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream, | |||
| 1813 | if (frames > cont) | 1814 | if (frames > cont) |
| 1814 | frames = cont; | 1815 | frames = cont; |
| 1815 | if (snd_BUG_ON(!frames)) { | 1816 | if (snd_BUG_ON(!frames)) { |
| 1817 | runtime->nowake = 0; | ||
| 1816 | snd_pcm_stream_unlock_irq(substream); | 1818 | snd_pcm_stream_unlock_irq(substream); |
| 1817 | return -EINVAL; | 1819 | return -EINVAL; |
| 1818 | } | 1820 | } |
| 1819 | appl_ptr = runtime->control->appl_ptr; | 1821 | appl_ptr = runtime->control->appl_ptr; |
| 1820 | appl_ofs = appl_ptr % runtime->buffer_size; | 1822 | appl_ofs = appl_ptr % runtime->buffer_size; |
| 1821 | snd_pcm_stream_unlock_irq(substream); | 1823 | snd_pcm_stream_unlock_irq(substream); |
| 1822 | if ((err = transfer(substream, appl_ofs, data, offset, frames)) < 0) | 1824 | err = transfer(substream, appl_ofs, data, offset, frames); |
| 1823 | goto _end; | ||
| 1824 | snd_pcm_stream_lock_irq(substream); | 1825 | snd_pcm_stream_lock_irq(substream); |
| 1826 | if (err < 0) | ||
| 1827 | goto _end_unlock; | ||
| 1825 | switch (runtime->status->state) { | 1828 | switch (runtime->status->state) { |
| 1826 | case SNDRV_PCM_STATE_XRUN: | 1829 | case SNDRV_PCM_STATE_XRUN: |
| 1827 | err = -EPIPE; | 1830 | err = -EPIPE; |
| @@ -1850,8 +1853,10 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream, | |||
| 1850 | } | 1853 | } |
| 1851 | } | 1854 | } |
| 1852 | _end_unlock: | 1855 | _end_unlock: |
| 1856 | runtime->nowake = 0; | ||
| 1857 | if (xfer > 0 && err >= 0) | ||
| 1858 | snd_pcm_update_state(substream, runtime); | ||
| 1853 | snd_pcm_stream_unlock_irq(substream); | 1859 | snd_pcm_stream_unlock_irq(substream); |
| 1854 | _end: | ||
| 1855 | return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; | 1860 | return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; |
| 1856 | } | 1861 | } |
| 1857 | 1862 | ||
| @@ -2009,6 +2014,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, | |||
| 2009 | goto _end_unlock; | 2014 | goto _end_unlock; |
| 2010 | } | 2015 | } |
| 2011 | 2016 | ||
| 2017 | runtime->nowake = 1; | ||
| 2012 | while (size > 0) { | 2018 | while (size > 0) { |
| 2013 | snd_pcm_uframes_t frames, appl_ptr, appl_ofs; | 2019 | snd_pcm_uframes_t frames, appl_ptr, appl_ofs; |
| 2014 | snd_pcm_uframes_t avail; | 2020 | snd_pcm_uframes_t avail; |
| @@ -2037,15 +2043,17 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, | |||
| 2037 | if (frames > cont) | 2043 | if (frames > cont) |
| 2038 | frames = cont; | 2044 | frames = cont; |
| 2039 | if (snd_BUG_ON(!frames)) { | 2045 | if (snd_BUG_ON(!frames)) { |
| 2046 | runtime->nowake = 0; | ||
| 2040 | snd_pcm_stream_unlock_irq(substream); | 2047 | snd_pcm_stream_unlock_irq(substream); |
| 2041 | return -EINVAL; | 2048 | return -EINVAL; |
| 2042 | } | 2049 | } |
| 2043 | appl_ptr = runtime->control->appl_ptr; | 2050 | appl_ptr = runtime->control->appl_ptr; |
| 2044 | appl_ofs = appl_ptr % runtime->buffer_size; | 2051 | appl_ofs = appl_ptr % runtime->buffer_size; |
| 2045 | snd_pcm_stream_unlock_irq(substream); | 2052 | snd_pcm_stream_unlock_irq(substream); |
| 2046 | if ((err = transfer(substream, appl_ofs, data, offset, frames)) < 0) | 2053 | err = transfer(substream, appl_ofs, data, offset, frames); |
| 2047 | goto _end; | ||
| 2048 | snd_pcm_stream_lock_irq(substream); | 2054 | snd_pcm_stream_lock_irq(substream); |
| 2055 | if (err < 0) | ||
| 2056 | goto _end_unlock; | ||
| 2049 | switch (runtime->status->state) { | 2057 | switch (runtime->status->state) { |
| 2050 | case SNDRV_PCM_STATE_XRUN: | 2058 | case SNDRV_PCM_STATE_XRUN: |
| 2051 | err = -EPIPE; | 2059 | err = -EPIPE; |
| @@ -2068,8 +2076,10 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream, | |||
| 2068 | xfer += frames; | 2076 | xfer += frames; |
| 2069 | } | 2077 | } |
| 2070 | _end_unlock: | 2078 | _end_unlock: |
| 2079 | runtime->nowake = 0; | ||
| 2080 | if (xfer > 0 && err >= 0) | ||
| 2081 | snd_pcm_update_state(substream, runtime); | ||
| 2071 | snd_pcm_stream_unlock_irq(substream); | 2082 | snd_pcm_stream_unlock_irq(substream); |
| 2072 | _end: | ||
| 2073 | return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; | 2083 | return xfer > 0 ? (snd_pcm_sframes_t)xfer : err; |
| 2074 | } | 2084 | } |
| 2075 | 2085 | ||
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 8e777f71717c..27284f628361 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
| @@ -516,6 +516,7 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream, | |||
| 516 | struct snd_pcm_sw_params *params) | 516 | struct snd_pcm_sw_params *params) |
| 517 | { | 517 | { |
| 518 | struct snd_pcm_runtime *runtime; | 518 | struct snd_pcm_runtime *runtime; |
| 519 | int err; | ||
| 519 | 520 | ||
| 520 | if (PCM_RUNTIME_CHECK(substream)) | 521 | if (PCM_RUNTIME_CHECK(substream)) |
| 521 | return -ENXIO; | 522 | return -ENXIO; |
| @@ -540,6 +541,7 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream, | |||
| 540 | if (params->silence_threshold > runtime->buffer_size) | 541 | if (params->silence_threshold > runtime->buffer_size) |
| 541 | return -EINVAL; | 542 | return -EINVAL; |
| 542 | } | 543 | } |
| 544 | err = 0; | ||
| 543 | snd_pcm_stream_lock_irq(substream); | 545 | snd_pcm_stream_lock_irq(substream); |
| 544 | runtime->tstamp_mode = params->tstamp_mode; | 546 | runtime->tstamp_mode = params->tstamp_mode; |
| 545 | runtime->period_step = params->period_step; | 547 | runtime->period_step = params->period_step; |
| @@ -553,10 +555,10 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream, | |||
| 553 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && | 555 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && |
| 554 | runtime->silence_size > 0) | 556 | runtime->silence_size > 0) |
| 555 | snd_pcm_playback_silence(substream, ULONG_MAX); | 557 | snd_pcm_playback_silence(substream, ULONG_MAX); |
| 556 | wake_up(&runtime->sleep); | 558 | err = snd_pcm_update_state(substream, runtime); |
| 557 | } | 559 | } |
| 558 | snd_pcm_stream_unlock_irq(substream); | 560 | snd_pcm_stream_unlock_irq(substream); |
| 559 | return 0; | 561 | return err; |
| 560 | } | 562 | } |
| 561 | 563 | ||
| 562 | static int snd_pcm_sw_params_user(struct snd_pcm_substream *substream, | 564 | static int snd_pcm_sw_params_user(struct snd_pcm_substream *substream, |
