diff options
author | Takashi Iwai <tiwai@suse.de> | 2015-01-23 10:18:42 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2015-01-28 01:21:27 -0500 |
commit | d8131e67f08bc15e54104cb69deb06bad9d87f30 (patch) | |
tree | 612f830a3ea36af5c3bb2249aa5e2d779dbaaa2e /sound/usb | |
parent | ad0119abe29fe3d506486a789de4c4619fa7602c (diff) |
ALSA: line6: Consolidate URB unlink and sync helpers
The codes to unlink and sync URBs are identical for both playback and
capture streams. Consolidate to single helper functions.
Tested-by: Chris Rorvick <chris@rorvick.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb')
-rw-r--r-- | sound/usb/line6/capture.c | 52 | ||||
-rw-r--r-- | sound/usb/line6/capture.h | 4 | ||||
-rw-r--r-- | sound/usb/line6/pcm.c | 90 | ||||
-rw-r--r-- | sound/usb/line6/playback.c | 52 | ||||
-rw-r--r-- | sound/usb/line6/playback.h | 4 |
5 files changed, 69 insertions, 133 deletions
diff --git a/sound/usb/line6/capture.c b/sound/usb/line6/capture.c index 439f1941eb56..1d477d7a42fb 100644 --- a/sound/usb/line6/capture.c +++ b/sound/usb/line6/capture.c | |||
@@ -85,58 +85,6 @@ int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm) | |||
85 | } | 85 | } |
86 | 86 | ||
87 | /* | 87 | /* |
88 | Unlink all currently active capture URBs. | ||
89 | */ | ||
90 | void line6_unlink_audio_in_urbs(struct snd_line6_pcm *line6pcm) | ||
91 | { | ||
92 | unsigned int i; | ||
93 | |||
94 | for (i = 0; i < LINE6_ISO_BUFFERS; i++) { | ||
95 | if (test_bit(i, &line6pcm->in.active_urbs)) { | ||
96 | if (!test_and_set_bit(i, &line6pcm->in.unlink_urbs)) { | ||
97 | struct urb *u = line6pcm->in.urbs[i]; | ||
98 | |||
99 | usb_unlink_urb(u); | ||
100 | } | ||
101 | } | ||
102 | } | ||
103 | } | ||
104 | |||
105 | /* | ||
106 | Wait until unlinking of all currently active capture URBs has been | ||
107 | finished. | ||
108 | */ | ||
109 | void line6_wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm) | ||
110 | { | ||
111 | int timeout = HZ; | ||
112 | unsigned int i; | ||
113 | int alive; | ||
114 | |||
115 | do { | ||
116 | alive = 0; | ||
117 | for (i = 0; i < LINE6_ISO_BUFFERS; i++) { | ||
118 | if (test_bit(i, &line6pcm->in.active_urbs)) | ||
119 | alive++; | ||
120 | } | ||
121 | if (!alive) | ||
122 | break; | ||
123 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
124 | schedule_timeout(1); | ||
125 | } while (--timeout > 0); | ||
126 | if (alive) | ||
127 | snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive); | ||
128 | } | ||
129 | |||
130 | /* | ||
131 | Unlink all currently active capture URBs, and wait for finishing. | ||
132 | */ | ||
133 | void line6_unlink_wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm) | ||
134 | { | ||
135 | line6_unlink_audio_in_urbs(line6pcm); | ||
136 | line6_wait_clear_audio_in_urbs(line6pcm); | ||
137 | } | ||
138 | |||
139 | /* | ||
140 | Copy data into ALSA capture buffer. | 88 | Copy data into ALSA capture buffer. |
141 | */ | 89 | */ |
142 | void line6_capture_copy(struct snd_line6_pcm *line6pcm, char *fbuf, int fsize) | 90 | void line6_capture_copy(struct snd_line6_pcm *line6pcm, char *fbuf, int fsize) |
diff --git a/sound/usb/line6/capture.h b/sound/usb/line6/capture.h index 0939f400a405..3cc71bc70b21 100644 --- a/sound/usb/line6/capture.h +++ b/sound/usb/line6/capture.h | |||
@@ -26,10 +26,6 @@ extern void line6_capture_check_period(struct snd_line6_pcm *line6pcm, | |||
26 | extern int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm); | 26 | extern int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm); |
27 | extern void line6_free_capture_buffer(struct snd_line6_pcm *line6pcm); | 27 | extern void line6_free_capture_buffer(struct snd_line6_pcm *line6pcm); |
28 | extern int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm); | 28 | extern int line6_submit_audio_in_all_urbs(struct snd_line6_pcm *line6pcm); |
29 | extern void line6_unlink_audio_in_urbs(struct snd_line6_pcm *line6pcm); | ||
30 | extern void line6_unlink_wait_clear_audio_in_urbs(struct snd_line6_pcm | ||
31 | *line6pcm); | ||
32 | extern void line6_wait_clear_audio_in_urbs(struct snd_line6_pcm *line6pcm); | ||
33 | extern int snd_line6_capture_trigger(struct snd_line6_pcm *line6pcm, int cmd); | 29 | extern int snd_line6_capture_trigger(struct snd_line6_pcm *line6pcm, int cmd); |
34 | 30 | ||
35 | #endif | 31 | #endif |
diff --git a/sound/usb/line6/pcm.c b/sound/usb/line6/pcm.c index 738bfd82cecd..677419dcacf9 100644 --- a/sound/usb/line6/pcm.c +++ b/sound/usb/line6/pcm.c | |||
@@ -90,6 +90,47 @@ static int snd_line6_impulse_period_put(struct snd_kcontrol *kcontrol, | |||
90 | return 1; | 90 | return 1; |
91 | } | 91 | } |
92 | 92 | ||
93 | /* | ||
94 | Unlink all currently active URBs. | ||
95 | */ | ||
96 | static void line6_unlink_audio_urbs(struct snd_line6_pcm *line6pcm, | ||
97 | struct line6_pcm_stream *pcms) | ||
98 | { | ||
99 | int i; | ||
100 | |||
101 | for (i = 0; i < LINE6_ISO_BUFFERS; i++) { | ||
102 | if (test_bit(i, &pcms->active_urbs)) { | ||
103 | if (!test_and_set_bit(i, &pcms->unlink_urbs)) | ||
104 | usb_unlink_urb(pcms->urbs[i]); | ||
105 | } | ||
106 | } | ||
107 | } | ||
108 | |||
109 | /* | ||
110 | Wait until unlinking of all currently active URBs has been finished. | ||
111 | */ | ||
112 | static void line6_wait_clear_audio_urbs(struct snd_line6_pcm *line6pcm, | ||
113 | struct line6_pcm_stream *pcms) | ||
114 | { | ||
115 | int timeout = HZ; | ||
116 | int i; | ||
117 | int alive; | ||
118 | |||
119 | do { | ||
120 | alive = 0; | ||
121 | for (i = 0; i < LINE6_ISO_BUFFERS; i++) { | ||
122 | if (test_bit(i, &pcms->active_urbs)) | ||
123 | alive++; | ||
124 | } | ||
125 | if (!alive) | ||
126 | break; | ||
127 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
128 | schedule_timeout(1); | ||
129 | } while (--timeout > 0); | ||
130 | if (alive) | ||
131 | snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive); | ||
132 | } | ||
133 | |||
93 | static bool test_flags(unsigned long flags0, unsigned long flags1, | 134 | static bool test_flags(unsigned long flags0, unsigned long flags1, |
94 | unsigned long mask) | 135 | unsigned long mask) |
95 | { | 136 | { |
@@ -202,18 +243,18 @@ int line6_pcm_release(struct snd_line6_pcm *line6pcm, int channels) | |||
202 | } while (cmpxchg(&line6pcm->flags, flags_old, flags_new) != flags_old); | 243 | } while (cmpxchg(&line6pcm->flags, flags_old, flags_new) != flags_old); |
203 | 244 | ||
204 | if (test_flags(flags_new, flags_old, LINE6_BITS_CAPTURE_STREAM)) | 245 | if (test_flags(flags_new, flags_old, LINE6_BITS_CAPTURE_STREAM)) |
205 | line6_unlink_audio_in_urbs(line6pcm); | 246 | line6_unlink_audio_urbs(line6pcm, &line6pcm->in); |
206 | 247 | ||
207 | if (test_flags(flags_new, flags_old, LINE6_BITS_CAPTURE_BUFFER)) { | 248 | if (test_flags(flags_new, flags_old, LINE6_BITS_CAPTURE_BUFFER)) { |
208 | line6_wait_clear_audio_in_urbs(line6pcm); | 249 | line6_wait_clear_audio_urbs(line6pcm, &line6pcm->in); |
209 | line6_free_capture_buffer(line6pcm); | 250 | line6_free_capture_buffer(line6pcm); |
210 | } | 251 | } |
211 | 252 | ||
212 | if (test_flags(flags_new, flags_old, LINE6_BITS_PLAYBACK_STREAM)) | 253 | if (test_flags(flags_new, flags_old, LINE6_BITS_PLAYBACK_STREAM)) |
213 | line6_unlink_audio_out_urbs(line6pcm); | 254 | line6_unlink_audio_urbs(line6pcm, &line6pcm->out); |
214 | 255 | ||
215 | if (test_flags(flags_new, flags_old, LINE6_BITS_PLAYBACK_BUFFER)) { | 256 | if (test_flags(flags_new, flags_old, LINE6_BITS_PLAYBACK_BUFFER)) { |
216 | line6_wait_clear_audio_out_urbs(line6pcm); | 257 | line6_wait_clear_audio_urbs(line6pcm, &line6pcm->out); |
217 | line6_free_playback_buffer(line6pcm); | 258 | line6_free_playback_buffer(line6pcm); |
218 | } | 259 | } |
219 | 260 | ||
@@ -325,21 +366,24 @@ static struct snd_kcontrol_new line6_controls[] = { | |||
325 | /* | 366 | /* |
326 | Cleanup the PCM device. | 367 | Cleanup the PCM device. |
327 | */ | 368 | */ |
328 | static void line6_cleanup_pcm(struct snd_pcm *pcm) | 369 | static void cleanup_urbs(struct line6_pcm_stream *pcms) |
329 | { | 370 | { |
330 | int i; | 371 | int i; |
331 | struct snd_line6_pcm *line6pcm = snd_pcm_chip(pcm); | ||
332 | 372 | ||
333 | for (i = 0; i < LINE6_ISO_BUFFERS; i++) { | 373 | for (i = 0; i < LINE6_ISO_BUFFERS; i++) { |
334 | if (line6pcm->out.urbs[i]) { | 374 | if (pcms->urbs[i]) { |
335 | usb_kill_urb(line6pcm->out.urbs[i]); | 375 | usb_kill_urb(pcms->urbs[i]); |
336 | usb_free_urb(line6pcm->out.urbs[i]); | 376 | usb_free_urb(pcms->urbs[i]); |
337 | } | ||
338 | if (line6pcm->in.urbs[i]) { | ||
339 | usb_kill_urb(line6pcm->in.urbs[i]); | ||
340 | usb_free_urb(line6pcm->in.urbs[i]); | ||
341 | } | 377 | } |
342 | } | 378 | } |
379 | } | ||
380 | |||
381 | static void line6_cleanup_pcm(struct snd_pcm *pcm) | ||
382 | { | ||
383 | struct snd_line6_pcm *line6pcm = snd_pcm_chip(pcm); | ||
384 | |||
385 | cleanup_urbs(&line6pcm->out); | ||
386 | cleanup_urbs(&line6pcm->in); | ||
343 | kfree(line6pcm); | 387 | kfree(line6pcm); |
344 | } | 388 | } |
345 | 389 | ||
@@ -374,8 +418,10 @@ static int snd_line6_new_pcm(struct usb_line6 *line6, struct snd_pcm **pcm_ret) | |||
374 | */ | 418 | */ |
375 | void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm) | 419 | void line6_pcm_disconnect(struct snd_line6_pcm *line6pcm) |
376 | { | 420 | { |
377 | line6_unlink_wait_clear_audio_out_urbs(line6pcm); | 421 | line6_unlink_audio_urbs(line6pcm, &line6pcm->out); |
378 | line6_unlink_wait_clear_audio_in_urbs(line6pcm); | 422 | line6_unlink_audio_urbs(line6pcm, &line6pcm->in); |
423 | line6_wait_clear_audio_urbs(line6pcm, &line6pcm->out); | ||
424 | line6_wait_clear_audio_urbs(line6pcm, &line6pcm->in); | ||
379 | } | 425 | } |
380 | 426 | ||
381 | /* | 427 | /* |
@@ -451,15 +497,17 @@ int snd_line6_prepare(struct snd_pcm_substream *substream) | |||
451 | 497 | ||
452 | switch (substream->stream) { | 498 | switch (substream->stream) { |
453 | case SNDRV_PCM_STREAM_PLAYBACK: | 499 | case SNDRV_PCM_STREAM_PLAYBACK: |
454 | if ((line6pcm->flags & LINE6_BITS_PLAYBACK_STREAM) == 0) | 500 | if ((line6pcm->flags & LINE6_BITS_PLAYBACK_STREAM) == 0) { |
455 | line6_unlink_wait_clear_audio_out_urbs(line6pcm); | 501 | line6_unlink_audio_urbs(line6pcm, &line6pcm->out); |
456 | 502 | line6_wait_clear_audio_urbs(line6pcm, &line6pcm->out); | |
503 | } | ||
457 | break; | 504 | break; |
458 | 505 | ||
459 | case SNDRV_PCM_STREAM_CAPTURE: | 506 | case SNDRV_PCM_STREAM_CAPTURE: |
460 | if ((line6pcm->flags & LINE6_BITS_CAPTURE_STREAM) == 0) | 507 | if ((line6pcm->flags & LINE6_BITS_CAPTURE_STREAM) == 0) { |
461 | line6_unlink_wait_clear_audio_in_urbs(line6pcm); | 508 | line6_unlink_audio_urbs(line6pcm, &line6pcm->in); |
462 | 509 | line6_wait_clear_audio_urbs(line6pcm, &line6pcm->in); | |
510 | } | ||
463 | break; | 511 | break; |
464 | } | 512 | } |
465 | 513 | ||
diff --git a/sound/usb/line6/playback.c b/sound/usb/line6/playback.c index d619c1718306..3820ed08b342 100644 --- a/sound/usb/line6/playback.c +++ b/sound/usb/line6/playback.c | |||
@@ -290,58 +290,6 @@ int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm) | |||
290 | return 0; | 290 | return 0; |
291 | } | 291 | } |
292 | 292 | ||
293 | /* | ||
294 | Unlink all currently active playback URBs. | ||
295 | */ | ||
296 | void line6_unlink_audio_out_urbs(struct snd_line6_pcm *line6pcm) | ||
297 | { | ||
298 | unsigned int i; | ||
299 | |||
300 | for (i = 0; i < LINE6_ISO_BUFFERS; i++) { | ||
301 | if (test_bit(i, &line6pcm->out.active_urbs)) { | ||
302 | if (!test_and_set_bit(i, &line6pcm->out.unlink_urbs)) { | ||
303 | struct urb *u = line6pcm->out.urbs[i]; | ||
304 | |||
305 | usb_unlink_urb(u); | ||
306 | } | ||
307 | } | ||
308 | } | ||
309 | } | ||
310 | |||
311 | /* | ||
312 | Wait until unlinking of all currently active playback URBs has been | ||
313 | finished. | ||
314 | */ | ||
315 | void line6_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm) | ||
316 | { | ||
317 | int timeout = HZ; | ||
318 | unsigned int i; | ||
319 | int alive; | ||
320 | |||
321 | do { | ||
322 | alive = 0; | ||
323 | for (i = 0; i < LINE6_ISO_BUFFERS; i++) { | ||
324 | if (test_bit(i, &line6pcm->out.active_urbs)) | ||
325 | alive++; | ||
326 | } | ||
327 | if (!alive) | ||
328 | break; | ||
329 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
330 | schedule_timeout(1); | ||
331 | } while (--timeout > 0); | ||
332 | if (alive) | ||
333 | snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive); | ||
334 | } | ||
335 | |||
336 | /* | ||
337 | Unlink all currently active playback URBs, and wait for finishing. | ||
338 | */ | ||
339 | void line6_unlink_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm) | ||
340 | { | ||
341 | line6_unlink_audio_out_urbs(line6pcm); | ||
342 | line6_wait_clear_audio_out_urbs(line6pcm); | ||
343 | } | ||
344 | |||
345 | void line6_free_playback_buffer(struct snd_line6_pcm *line6pcm) | 293 | void line6_free_playback_buffer(struct snd_line6_pcm *line6pcm) |
346 | { | 294 | { |
347 | kfree(line6pcm->out.buffer); | 295 | kfree(line6pcm->out.buffer); |
diff --git a/sound/usb/line6/playback.h b/sound/usb/line6/playback.h index 78a885113221..52a278353d3b 100644 --- a/sound/usb/line6/playback.h +++ b/sound/usb/line6/playback.h | |||
@@ -32,10 +32,6 @@ extern struct snd_pcm_ops snd_line6_playback_ops; | |||
32 | extern int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm); | 32 | extern int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm); |
33 | extern void line6_free_playback_buffer(struct snd_line6_pcm *line6pcm); | 33 | extern void line6_free_playback_buffer(struct snd_line6_pcm *line6pcm); |
34 | extern int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm); | 34 | extern int line6_submit_audio_out_all_urbs(struct snd_line6_pcm *line6pcm); |
35 | extern void line6_unlink_audio_out_urbs(struct snd_line6_pcm *line6pcm); | ||
36 | extern void line6_unlink_wait_clear_audio_out_urbs(struct snd_line6_pcm | ||
37 | *line6pcm); | ||
38 | extern void line6_wait_clear_audio_out_urbs(struct snd_line6_pcm *line6pcm); | ||
39 | extern int snd_line6_playback_trigger(struct snd_line6_pcm *line6pcm, int cmd); | 35 | extern int snd_line6_playback_trigger(struct snd_line6_pcm *line6pcm, int cmd); |
40 | 36 | ||
41 | #endif | 37 | #endif |