diff options
| -rw-r--r-- | sound/core/pcm_lib.c | 33 |
1 files changed, 24 insertions, 9 deletions
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 86d0caf91b35..62e90b862a0d 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
| @@ -1761,6 +1761,10 @@ static int wait_for_avail(struct snd_pcm_substream *substream, | |||
| 1761 | snd_pcm_uframes_t avail = 0; | 1761 | snd_pcm_uframes_t avail = 0; |
| 1762 | long wait_time, tout; | 1762 | long wait_time, tout; |
| 1763 | 1763 | ||
| 1764 | init_waitqueue_entry(&wait, current); | ||
| 1765 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 1766 | add_wait_queue(&runtime->tsleep, &wait); | ||
| 1767 | |||
| 1764 | if (runtime->no_period_wakeup) | 1768 | if (runtime->no_period_wakeup) |
| 1765 | wait_time = MAX_SCHEDULE_TIMEOUT; | 1769 | wait_time = MAX_SCHEDULE_TIMEOUT; |
| 1766 | else { | 1770 | else { |
| @@ -1771,16 +1775,32 @@ static int wait_for_avail(struct snd_pcm_substream *substream, | |||
| 1771 | } | 1775 | } |
| 1772 | wait_time = msecs_to_jiffies(wait_time * 1000); | 1776 | wait_time = msecs_to_jiffies(wait_time * 1000); |
| 1773 | } | 1777 | } |
| 1774 | init_waitqueue_entry(&wait, current); | 1778 | |
| 1775 | add_wait_queue(&runtime->tsleep, &wait); | ||
| 1776 | for (;;) { | 1779 | for (;;) { |
| 1777 | if (signal_pending(current)) { | 1780 | if (signal_pending(current)) { |
| 1778 | err = -ERESTARTSYS; | 1781 | err = -ERESTARTSYS; |
| 1779 | break; | 1782 | break; |
| 1780 | } | 1783 | } |
| 1784 | |||
| 1785 | /* | ||
| 1786 | * We need to check if space became available already | ||
| 1787 | * (and thus the wakeup happened already) first to close | ||
| 1788 | * the race of space already having become available. | ||
| 1789 | * This check must happen after been added to the waitqueue | ||
| 1790 | * and having current state be INTERRUPTIBLE. | ||
| 1791 | */ | ||
| 1792 | if (is_playback) | ||
| 1793 | avail = snd_pcm_playback_avail(runtime); | ||
| 1794 | else | ||
| 1795 | avail = snd_pcm_capture_avail(runtime); | ||
| 1796 | if (avail >= runtime->twake) | ||
| 1797 | break; | ||
| 1781 | snd_pcm_stream_unlock_irq(substream); | 1798 | snd_pcm_stream_unlock_irq(substream); |
| 1782 | tout = schedule_timeout_interruptible(wait_time); | 1799 | |
| 1800 | tout = schedule_timeout(wait_time); | ||
| 1801 | |||
| 1783 | snd_pcm_stream_lock_irq(substream); | 1802 | snd_pcm_stream_lock_irq(substream); |
| 1803 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 1784 | switch (runtime->status->state) { | 1804 | switch (runtime->status->state) { |
| 1785 | case SNDRV_PCM_STATE_SUSPENDED: | 1805 | case SNDRV_PCM_STATE_SUSPENDED: |
| 1786 | err = -ESTRPIPE; | 1806 | err = -ESTRPIPE; |
| @@ -1806,14 +1826,9 @@ static int wait_for_avail(struct snd_pcm_substream *substream, | |||
| 1806 | err = -EIO; | 1826 | err = -EIO; |
| 1807 | break; | 1827 | break; |
| 1808 | } | 1828 | } |
| 1809 | if (is_playback) | ||
| 1810 | avail = snd_pcm_playback_avail(runtime); | ||
| 1811 | else | ||
| 1812 | avail = snd_pcm_capture_avail(runtime); | ||
| 1813 | if (avail >= runtime->twake) | ||
| 1814 | break; | ||
| 1815 | } | 1829 | } |
| 1816 | _endloop: | 1830 | _endloop: |
| 1831 | set_current_state(TASK_RUNNING); | ||
| 1817 | remove_wait_queue(&runtime->tsleep, &wait); | 1832 | remove_wait_queue(&runtime->tsleep, &wait); |
| 1818 | *availp = avail; | 1833 | *availp = avail; |
| 1819 | return err; | 1834 | return err; |
