diff options
Diffstat (limited to 'sound/core/pcm_native.c')
-rw-r--r-- | sound/core/pcm_native.c | 261 |
1 files changed, 102 insertions, 159 deletions
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 0e875d5a9e86..04c6301394d0 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
@@ -99,6 +99,57 @@ static inline void down_write_nonblock(struct rw_semaphore *lock) | |||
99 | cond_resched(); | 99 | cond_resched(); |
100 | } | 100 | } |
101 | 101 | ||
102 | #define PCM_LOCK_DEFAULT 0 | ||
103 | #define PCM_LOCK_IRQ 1 | ||
104 | #define PCM_LOCK_IRQSAVE 2 | ||
105 | |||
106 | static unsigned long __snd_pcm_stream_lock_mode(struct snd_pcm_substream *substream, | ||
107 | unsigned int mode) | ||
108 | { | ||
109 | unsigned long flags = 0; | ||
110 | if (substream->pcm->nonatomic) { | ||
111 | down_read_nested(&snd_pcm_link_rwsem, SINGLE_DEPTH_NESTING); | ||
112 | mutex_lock(&substream->self_group.mutex); | ||
113 | } else { | ||
114 | switch (mode) { | ||
115 | case PCM_LOCK_DEFAULT: | ||
116 | read_lock(&snd_pcm_link_rwlock); | ||
117 | break; | ||
118 | case PCM_LOCK_IRQ: | ||
119 | read_lock_irq(&snd_pcm_link_rwlock); | ||
120 | break; | ||
121 | case PCM_LOCK_IRQSAVE: | ||
122 | read_lock_irqsave(&snd_pcm_link_rwlock, flags); | ||
123 | break; | ||
124 | } | ||
125 | spin_lock(&substream->self_group.lock); | ||
126 | } | ||
127 | return flags; | ||
128 | } | ||
129 | |||
130 | static void __snd_pcm_stream_unlock_mode(struct snd_pcm_substream *substream, | ||
131 | unsigned int mode, unsigned long flags) | ||
132 | { | ||
133 | if (substream->pcm->nonatomic) { | ||
134 | mutex_unlock(&substream->self_group.mutex); | ||
135 | up_read(&snd_pcm_link_rwsem); | ||
136 | } else { | ||
137 | spin_unlock(&substream->self_group.lock); | ||
138 | |||
139 | switch (mode) { | ||
140 | case PCM_LOCK_DEFAULT: | ||
141 | read_unlock(&snd_pcm_link_rwlock); | ||
142 | break; | ||
143 | case PCM_LOCK_IRQ: | ||
144 | read_unlock_irq(&snd_pcm_link_rwlock); | ||
145 | break; | ||
146 | case PCM_LOCK_IRQSAVE: | ||
147 | read_unlock_irqrestore(&snd_pcm_link_rwlock, flags); | ||
148 | break; | ||
149 | } | ||
150 | } | ||
151 | } | ||
152 | |||
102 | /** | 153 | /** |
103 | * snd_pcm_stream_lock - Lock the PCM stream | 154 | * snd_pcm_stream_lock - Lock the PCM stream |
104 | * @substream: PCM substream | 155 | * @substream: PCM substream |
@@ -109,13 +160,7 @@ static inline void down_write_nonblock(struct rw_semaphore *lock) | |||
109 | */ | 160 | */ |
110 | void snd_pcm_stream_lock(struct snd_pcm_substream *substream) | 161 | void snd_pcm_stream_lock(struct snd_pcm_substream *substream) |
111 | { | 162 | { |
112 | if (substream->pcm->nonatomic) { | 163 | __snd_pcm_stream_lock_mode(substream, PCM_LOCK_DEFAULT); |
113 | down_read_nested(&snd_pcm_link_rwsem, SINGLE_DEPTH_NESTING); | ||
114 | mutex_lock(&substream->self_group.mutex); | ||
115 | } else { | ||
116 | read_lock(&snd_pcm_link_rwlock); | ||
117 | spin_lock(&substream->self_group.lock); | ||
118 | } | ||
119 | } | 164 | } |
120 | EXPORT_SYMBOL_GPL(snd_pcm_stream_lock); | 165 | EXPORT_SYMBOL_GPL(snd_pcm_stream_lock); |
121 | 166 | ||
@@ -127,13 +172,7 @@ EXPORT_SYMBOL_GPL(snd_pcm_stream_lock); | |||
127 | */ | 172 | */ |
128 | void snd_pcm_stream_unlock(struct snd_pcm_substream *substream) | 173 | void snd_pcm_stream_unlock(struct snd_pcm_substream *substream) |
129 | { | 174 | { |
130 | if (substream->pcm->nonatomic) { | 175 | __snd_pcm_stream_unlock_mode(substream, PCM_LOCK_DEFAULT, 0); |
131 | mutex_unlock(&substream->self_group.mutex); | ||
132 | up_read(&snd_pcm_link_rwsem); | ||
133 | } else { | ||
134 | spin_unlock(&substream->self_group.lock); | ||
135 | read_unlock(&snd_pcm_link_rwlock); | ||
136 | } | ||
137 | } | 176 | } |
138 | EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock); | 177 | EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock); |
139 | 178 | ||
@@ -147,9 +186,7 @@ EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock); | |||
147 | */ | 186 | */ |
148 | void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream) | 187 | void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream) |
149 | { | 188 | { |
150 | if (!substream->pcm->nonatomic) | 189 | __snd_pcm_stream_lock_mode(substream, PCM_LOCK_IRQ); |
151 | local_irq_disable(); | ||
152 | snd_pcm_stream_lock(substream); | ||
153 | } | 190 | } |
154 | EXPORT_SYMBOL_GPL(snd_pcm_stream_lock_irq); | 191 | EXPORT_SYMBOL_GPL(snd_pcm_stream_lock_irq); |
155 | 192 | ||
@@ -161,19 +198,13 @@ EXPORT_SYMBOL_GPL(snd_pcm_stream_lock_irq); | |||
161 | */ | 198 | */ |
162 | void snd_pcm_stream_unlock_irq(struct snd_pcm_substream *substream) | 199 | void snd_pcm_stream_unlock_irq(struct snd_pcm_substream *substream) |
163 | { | 200 | { |
164 | snd_pcm_stream_unlock(substream); | 201 | __snd_pcm_stream_unlock_mode(substream, PCM_LOCK_IRQ, 0); |
165 | if (!substream->pcm->nonatomic) | ||
166 | local_irq_enable(); | ||
167 | } | 202 | } |
168 | EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irq); | 203 | EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irq); |
169 | 204 | ||
170 | unsigned long _snd_pcm_stream_lock_irqsave(struct snd_pcm_substream *substream) | 205 | unsigned long _snd_pcm_stream_lock_irqsave(struct snd_pcm_substream *substream) |
171 | { | 206 | { |
172 | unsigned long flags = 0; | 207 | return __snd_pcm_stream_lock_mode(substream, PCM_LOCK_IRQSAVE); |
173 | if (!substream->pcm->nonatomic) | ||
174 | local_irq_save(flags); | ||
175 | snd_pcm_stream_lock(substream); | ||
176 | return flags; | ||
177 | } | 208 | } |
178 | EXPORT_SYMBOL_GPL(_snd_pcm_stream_lock_irqsave); | 209 | EXPORT_SYMBOL_GPL(_snd_pcm_stream_lock_irqsave); |
179 | 210 | ||
@@ -187,9 +218,7 @@ EXPORT_SYMBOL_GPL(_snd_pcm_stream_lock_irqsave); | |||
187 | void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream, | 218 | void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream, |
188 | unsigned long flags) | 219 | unsigned long flags) |
189 | { | 220 | { |
190 | snd_pcm_stream_unlock(substream); | 221 | __snd_pcm_stream_unlock_mode(substream, PCM_LOCK_IRQSAVE, flags); |
191 | if (!substream->pcm->nonatomic) | ||
192 | local_irq_restore(flags); | ||
193 | } | 222 | } |
194 | EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore); | 223 | EXPORT_SYMBOL_GPL(snd_pcm_stream_unlock_irqrestore); |
195 | 224 | ||
@@ -857,6 +886,18 @@ static int snd_pcm_sw_params_user(struct snd_pcm_substream *substream, | |||
857 | return err; | 886 | return err; |
858 | } | 887 | } |
859 | 888 | ||
889 | static inline snd_pcm_uframes_t | ||
890 | snd_pcm_calc_delay(struct snd_pcm_substream *substream) | ||
891 | { | ||
892 | snd_pcm_uframes_t delay; | ||
893 | |||
894 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
895 | delay = snd_pcm_playback_hw_avail(substream->runtime); | ||
896 | else | ||
897 | delay = snd_pcm_capture_avail(substream->runtime); | ||
898 | return delay + substream->runtime->delay; | ||
899 | } | ||
900 | |||
860 | int snd_pcm_status(struct snd_pcm_substream *substream, | 901 | int snd_pcm_status(struct snd_pcm_substream *substream, |
861 | struct snd_pcm_status *status) | 902 | struct snd_pcm_status *status) |
862 | { | 903 | { |
@@ -908,21 +949,9 @@ int snd_pcm_status(struct snd_pcm_substream *substream, | |||
908 | _tstamp_end: | 949 | _tstamp_end: |
909 | status->appl_ptr = runtime->control->appl_ptr; | 950 | status->appl_ptr = runtime->control->appl_ptr; |
910 | status->hw_ptr = runtime->status->hw_ptr; | 951 | status->hw_ptr = runtime->status->hw_ptr; |
911 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 952 | status->avail = snd_pcm_avail(substream); |
912 | status->avail = snd_pcm_playback_avail(runtime); | 953 | status->delay = snd_pcm_running(substream) ? |
913 | if (runtime->status->state == SNDRV_PCM_STATE_RUNNING || | 954 | snd_pcm_calc_delay(substream) : 0; |
914 | runtime->status->state == SNDRV_PCM_STATE_DRAINING) { | ||
915 | status->delay = runtime->buffer_size - status->avail; | ||
916 | status->delay += runtime->delay; | ||
917 | } else | ||
918 | status->delay = 0; | ||
919 | } else { | ||
920 | status->avail = snd_pcm_capture_avail(runtime); | ||
921 | if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) | ||
922 | status->delay = status->avail + runtime->delay; | ||
923 | else | ||
924 | status->delay = 0; | ||
925 | } | ||
926 | status->avail_max = runtime->avail_max; | 955 | status->avail_max = runtime->avail_max; |
927 | status->overrange = runtime->overrange; | 956 | status->overrange = runtime->overrange; |
928 | runtime->avail_max = 0; | 957 | runtime->avail_max = 0; |
@@ -2610,10 +2639,9 @@ static snd_pcm_sframes_t rewind_appl_ptr(struct snd_pcm_substream *substream, | |||
2610 | return ret < 0 ? 0 : frames; | 2639 | return ret < 0 ? 0 : frames; |
2611 | } | 2640 | } |
2612 | 2641 | ||
2613 | static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *substream, | 2642 | static snd_pcm_sframes_t snd_pcm_rewind(struct snd_pcm_substream *substream, |
2614 | snd_pcm_uframes_t frames) | 2643 | snd_pcm_uframes_t frames) |
2615 | { | 2644 | { |
2616 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
2617 | snd_pcm_sframes_t ret; | 2645 | snd_pcm_sframes_t ret; |
2618 | 2646 | ||
2619 | if (frames == 0) | 2647 | if (frames == 0) |
@@ -2623,33 +2651,14 @@ static snd_pcm_sframes_t snd_pcm_playback_rewind(struct snd_pcm_substream *subst | |||
2623 | ret = do_pcm_hwsync(substream); | 2651 | ret = do_pcm_hwsync(substream); |
2624 | if (!ret) | 2652 | if (!ret) |
2625 | ret = rewind_appl_ptr(substream, frames, | 2653 | ret = rewind_appl_ptr(substream, frames, |
2626 | snd_pcm_playback_hw_avail(runtime)); | 2654 | snd_pcm_hw_avail(substream)); |
2627 | snd_pcm_stream_unlock_irq(substream); | 2655 | snd_pcm_stream_unlock_irq(substream); |
2628 | return ret; | 2656 | return ret; |
2629 | } | 2657 | } |
2630 | 2658 | ||
2631 | static snd_pcm_sframes_t snd_pcm_capture_rewind(struct snd_pcm_substream *substream, | 2659 | static snd_pcm_sframes_t snd_pcm_forward(struct snd_pcm_substream *substream, |
2632 | snd_pcm_uframes_t frames) | 2660 | snd_pcm_uframes_t frames) |
2633 | { | 2661 | { |
2634 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
2635 | snd_pcm_sframes_t ret; | ||
2636 | |||
2637 | if (frames == 0) | ||
2638 | return 0; | ||
2639 | |||
2640 | snd_pcm_stream_lock_irq(substream); | ||
2641 | ret = do_pcm_hwsync(substream); | ||
2642 | if (!ret) | ||
2643 | ret = rewind_appl_ptr(substream, frames, | ||
2644 | snd_pcm_capture_hw_avail(runtime)); | ||
2645 | snd_pcm_stream_unlock_irq(substream); | ||
2646 | return ret; | ||
2647 | } | ||
2648 | |||
2649 | static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *substream, | ||
2650 | snd_pcm_uframes_t frames) | ||
2651 | { | ||
2652 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
2653 | snd_pcm_sframes_t ret; | 2662 | snd_pcm_sframes_t ret; |
2654 | 2663 | ||
2655 | if (frames == 0) | 2664 | if (frames == 0) |
@@ -2659,25 +2668,7 @@ static snd_pcm_sframes_t snd_pcm_playback_forward(struct snd_pcm_substream *subs | |||
2659 | ret = do_pcm_hwsync(substream); | 2668 | ret = do_pcm_hwsync(substream); |
2660 | if (!ret) | 2669 | if (!ret) |
2661 | ret = forward_appl_ptr(substream, frames, | 2670 | ret = forward_appl_ptr(substream, frames, |
2662 | snd_pcm_playback_avail(runtime)); | 2671 | snd_pcm_avail(substream)); |
2663 | snd_pcm_stream_unlock_irq(substream); | ||
2664 | return ret; | ||
2665 | } | ||
2666 | |||
2667 | static snd_pcm_sframes_t snd_pcm_capture_forward(struct snd_pcm_substream *substream, | ||
2668 | snd_pcm_uframes_t frames) | ||
2669 | { | ||
2670 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
2671 | snd_pcm_sframes_t ret; | ||
2672 | |||
2673 | if (frames == 0) | ||
2674 | return 0; | ||
2675 | |||
2676 | snd_pcm_stream_lock_irq(substream); | ||
2677 | ret = do_pcm_hwsync(substream); | ||
2678 | if (!ret) | ||
2679 | ret = forward_appl_ptr(substream, frames, | ||
2680 | snd_pcm_capture_avail(runtime)); | ||
2681 | snd_pcm_stream_unlock_irq(substream); | 2672 | snd_pcm_stream_unlock_irq(substream); |
2682 | return ret; | 2673 | return ret; |
2683 | } | 2674 | } |
@@ -2695,19 +2686,13 @@ static int snd_pcm_hwsync(struct snd_pcm_substream *substream) | |||
2695 | static int snd_pcm_delay(struct snd_pcm_substream *substream, | 2686 | static int snd_pcm_delay(struct snd_pcm_substream *substream, |
2696 | snd_pcm_sframes_t *delay) | 2687 | snd_pcm_sframes_t *delay) |
2697 | { | 2688 | { |
2698 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
2699 | int err; | 2689 | int err; |
2700 | snd_pcm_sframes_t n = 0; | 2690 | snd_pcm_sframes_t n = 0; |
2701 | 2691 | ||
2702 | snd_pcm_stream_lock_irq(substream); | 2692 | snd_pcm_stream_lock_irq(substream); |
2703 | err = do_pcm_hwsync(substream); | 2693 | err = do_pcm_hwsync(substream); |
2704 | if (!err) { | 2694 | if (!err) |
2705 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 2695 | n = snd_pcm_calc_delay(substream); |
2706 | n = snd_pcm_playback_hw_avail(runtime); | ||
2707 | else | ||
2708 | n = snd_pcm_capture_avail(runtime); | ||
2709 | n += runtime->delay; | ||
2710 | } | ||
2711 | snd_pcm_stream_unlock_irq(substream); | 2696 | snd_pcm_stream_unlock_irq(substream); |
2712 | if (!err) | 2697 | if (!err) |
2713 | *delay = n; | 2698 | *delay = n; |
@@ -2834,10 +2819,7 @@ static int snd_pcm_rewind_ioctl(struct snd_pcm_substream *substream, | |||
2834 | return -EFAULT; | 2819 | return -EFAULT; |
2835 | if (put_user(0, _frames)) | 2820 | if (put_user(0, _frames)) |
2836 | return -EFAULT; | 2821 | return -EFAULT; |
2837 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 2822 | result = snd_pcm_rewind(substream, frames); |
2838 | result = snd_pcm_playback_rewind(substream, frames); | ||
2839 | else | ||
2840 | result = snd_pcm_capture_rewind(substream, frames); | ||
2841 | __put_user(result, _frames); | 2823 | __put_user(result, _frames); |
2842 | return result < 0 ? result : 0; | 2824 | return result < 0 ? result : 0; |
2843 | } | 2825 | } |
@@ -2852,10 +2834,7 @@ static int snd_pcm_forward_ioctl(struct snd_pcm_substream *substream, | |||
2852 | return -EFAULT; | 2834 | return -EFAULT; |
2853 | if (put_user(0, _frames)) | 2835 | if (put_user(0, _frames)) |
2854 | return -EFAULT; | 2836 | return -EFAULT; |
2855 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 2837 | result = snd_pcm_forward(substream, frames); |
2856 | result = snd_pcm_playback_forward(substream, frames); | ||
2857 | else | ||
2858 | result = snd_pcm_capture_forward(substream, frames); | ||
2859 | __put_user(result, _frames); | 2838 | __put_user(result, _frames); |
2860 | return result < 0 ? result : 0; | 2839 | return result < 0 ? result : 0; |
2861 | } | 2840 | } |
@@ -2998,7 +2977,7 @@ int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream, | |||
2998 | /* provided only for OSS; capture-only and no value returned */ | 2977 | /* provided only for OSS; capture-only and no value returned */ |
2999 | if (substream->stream != SNDRV_PCM_STREAM_CAPTURE) | 2978 | if (substream->stream != SNDRV_PCM_STREAM_CAPTURE) |
3000 | return -EINVAL; | 2979 | return -EINVAL; |
3001 | result = snd_pcm_capture_forward(substream, *frames); | 2980 | result = snd_pcm_forward(substream, *frames); |
3002 | return result < 0 ? result : 0; | 2981 | return result < 0 ? result : 0; |
3003 | } | 2982 | } |
3004 | case SNDRV_PCM_IOCTL_HW_PARAMS: | 2983 | case SNDRV_PCM_IOCTL_HW_PARAMS: |
@@ -3140,82 +3119,46 @@ static ssize_t snd_pcm_writev(struct kiocb *iocb, struct iov_iter *from) | |||
3140 | return result; | 3119 | return result; |
3141 | } | 3120 | } |
3142 | 3121 | ||
3143 | static __poll_t snd_pcm_playback_poll(struct file *file, poll_table * wait) | 3122 | static __poll_t snd_pcm_poll(struct file *file, poll_table *wait) |
3144 | { | 3123 | { |
3145 | struct snd_pcm_file *pcm_file; | 3124 | struct snd_pcm_file *pcm_file; |
3146 | struct snd_pcm_substream *substream; | 3125 | struct snd_pcm_substream *substream; |
3147 | struct snd_pcm_runtime *runtime; | 3126 | struct snd_pcm_runtime *runtime; |
3148 | __poll_t mask; | 3127 | __poll_t mask, ok; |
3149 | snd_pcm_uframes_t avail; | 3128 | snd_pcm_uframes_t avail; |
3150 | 3129 | ||
3151 | pcm_file = file->private_data; | 3130 | pcm_file = file->private_data; |
3152 | 3131 | ||
3153 | substream = pcm_file->substream; | 3132 | substream = pcm_file->substream; |
3133 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
3134 | ok = EPOLLOUT | EPOLLWRNORM; | ||
3135 | else | ||
3136 | ok = EPOLLIN | EPOLLRDNORM; | ||
3154 | if (PCM_RUNTIME_CHECK(substream)) | 3137 | if (PCM_RUNTIME_CHECK(substream)) |
3155 | return EPOLLOUT | EPOLLWRNORM | EPOLLERR; | 3138 | return ok | EPOLLERR; |
3156 | runtime = substream->runtime; | ||
3157 | |||
3158 | poll_wait(file, &runtime->sleep, wait); | ||
3159 | 3139 | ||
3160 | snd_pcm_stream_lock_irq(substream); | ||
3161 | avail = snd_pcm_playback_avail(runtime); | ||
3162 | switch (runtime->status->state) { | ||
3163 | case SNDRV_PCM_STATE_RUNNING: | ||
3164 | case SNDRV_PCM_STATE_PREPARED: | ||
3165 | case SNDRV_PCM_STATE_PAUSED: | ||
3166 | if (avail >= runtime->control->avail_min) { | ||
3167 | mask = EPOLLOUT | EPOLLWRNORM; | ||
3168 | break; | ||
3169 | } | ||
3170 | /* Fall through */ | ||
3171 | case SNDRV_PCM_STATE_DRAINING: | ||
3172 | mask = 0; | ||
3173 | break; | ||
3174 | default: | ||
3175 | mask = EPOLLOUT | EPOLLWRNORM | EPOLLERR; | ||
3176 | break; | ||
3177 | } | ||
3178 | snd_pcm_stream_unlock_irq(substream); | ||
3179 | return mask; | ||
3180 | } | ||
3181 | |||
3182 | static __poll_t snd_pcm_capture_poll(struct file *file, poll_table * wait) | ||
3183 | { | ||
3184 | struct snd_pcm_file *pcm_file; | ||
3185 | struct snd_pcm_substream *substream; | ||
3186 | struct snd_pcm_runtime *runtime; | ||
3187 | __poll_t mask; | ||
3188 | snd_pcm_uframes_t avail; | ||
3189 | |||
3190 | pcm_file = file->private_data; | ||
3191 | |||
3192 | substream = pcm_file->substream; | ||
3193 | if (PCM_RUNTIME_CHECK(substream)) | ||
3194 | return EPOLLIN | EPOLLRDNORM | EPOLLERR; | ||
3195 | runtime = substream->runtime; | 3140 | runtime = substream->runtime; |
3196 | |||
3197 | poll_wait(file, &runtime->sleep, wait); | 3141 | poll_wait(file, &runtime->sleep, wait); |
3198 | 3142 | ||
3143 | mask = 0; | ||
3199 | snd_pcm_stream_lock_irq(substream); | 3144 | snd_pcm_stream_lock_irq(substream); |
3200 | avail = snd_pcm_capture_avail(runtime); | 3145 | avail = snd_pcm_avail(substream); |
3201 | switch (runtime->status->state) { | 3146 | switch (runtime->status->state) { |
3202 | case SNDRV_PCM_STATE_RUNNING: | 3147 | case SNDRV_PCM_STATE_RUNNING: |
3203 | case SNDRV_PCM_STATE_PREPARED: | 3148 | case SNDRV_PCM_STATE_PREPARED: |
3204 | case SNDRV_PCM_STATE_PAUSED: | 3149 | case SNDRV_PCM_STATE_PAUSED: |
3205 | if (avail >= runtime->control->avail_min) { | 3150 | if (avail >= runtime->control->avail_min) |
3206 | mask = EPOLLIN | EPOLLRDNORM; | 3151 | mask = ok; |
3207 | break; | ||
3208 | } | ||
3209 | mask = 0; | ||
3210 | break; | 3152 | break; |
3211 | case SNDRV_PCM_STATE_DRAINING: | 3153 | case SNDRV_PCM_STATE_DRAINING: |
3212 | if (avail > 0) { | 3154 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { |
3213 | mask = EPOLLIN | EPOLLRDNORM; | 3155 | mask = ok; |
3214 | break; | 3156 | if (!avail) |
3157 | mask |= EPOLLERR; | ||
3215 | } | 3158 | } |
3216 | /* Fall through */ | 3159 | break; |
3217 | default: | 3160 | default: |
3218 | mask = EPOLLIN | EPOLLRDNORM | EPOLLERR; | 3161 | mask = ok | EPOLLERR; |
3219 | break; | 3162 | break; |
3220 | } | 3163 | } |
3221 | snd_pcm_stream_unlock_irq(substream); | 3164 | snd_pcm_stream_unlock_irq(substream); |
@@ -3707,7 +3650,7 @@ const struct file_operations snd_pcm_f_ops[2] = { | |||
3707 | .open = snd_pcm_playback_open, | 3650 | .open = snd_pcm_playback_open, |
3708 | .release = snd_pcm_release, | 3651 | .release = snd_pcm_release, |
3709 | .llseek = no_llseek, | 3652 | .llseek = no_llseek, |
3710 | .poll = snd_pcm_playback_poll, | 3653 | .poll = snd_pcm_poll, |
3711 | .unlocked_ioctl = snd_pcm_ioctl, | 3654 | .unlocked_ioctl = snd_pcm_ioctl, |
3712 | .compat_ioctl = snd_pcm_ioctl_compat, | 3655 | .compat_ioctl = snd_pcm_ioctl_compat, |
3713 | .mmap = snd_pcm_mmap, | 3656 | .mmap = snd_pcm_mmap, |
@@ -3721,7 +3664,7 @@ const struct file_operations snd_pcm_f_ops[2] = { | |||
3721 | .open = snd_pcm_capture_open, | 3664 | .open = snd_pcm_capture_open, |
3722 | .release = snd_pcm_release, | 3665 | .release = snd_pcm_release, |
3723 | .llseek = no_llseek, | 3666 | .llseek = no_llseek, |
3724 | .poll = snd_pcm_capture_poll, | 3667 | .poll = snd_pcm_poll, |
3725 | .unlocked_ioctl = snd_pcm_ioctl, | 3668 | .unlocked_ioctl = snd_pcm_ioctl, |
3726 | .compat_ioctl = snd_pcm_ioctl_compat, | 3669 | .compat_ioctl = snd_pcm_ioctl_compat, |
3727 | .mmap = snd_pcm_mmap, | 3670 | .mmap = snd_pcm_mmap, |