summaryrefslogtreecommitdiff
path: root/sound/usb/line6/toneport.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2015-01-27 15:24:09 +0100
committerTakashi Iwai <tiwai@suse.de>2015-01-28 07:22:36 +0100
commit63e20df1e5b2ef8d871ecbdb6c038d554ed1ca74 (patch)
treeaff5e07f44901d5800eabd4fddc501c20cf9f1af /sound/usb/line6/toneport.c
parentf2bb614bb6c7f5245521195f144272ef93d9f086 (diff)
downloadlinux-63e20df1e5b2ef8d871ecbdb6c038d554ed1ca74.tar.gz
linux-63e20df1e5b2ef8d871ecbdb6c038d554ed1ca74.tar.xz
ALSA: line6: Reorganize PCM stream handling
The current code deals with the stream start / stop solely via line6_pcm_acquire() and line6_pcm_release(). This was (supposedly) intended to avoid the races, but it doesn't work as expected. The concurrent acquire and release calls can be performed without proper protections, thus this might result in memory corruption. Furthermore, we can't take a mutex to protect the whole function because it can be called from the PCM trigger callback that is an atomic context. Also spinlock isn't appropriate because the function allocates with kmalloc with GFP_KERNEL. That is, these function just lead to singular problems. This is an attempt to reduce the existing races. First off, separate both the stream buffer management and the stream URB management. The former is protected via a newly introduced state_mutex while the latter is protected via each line6_pcm_stream lock. Secondly, the stream state are now managed in opened and running bit flags of each line6_pcm_stream. Not only this a bit clearer than previous combined bit flags, this also gives a better abstraction. These rewrites allows us to make common hw_params and hw_free callbacks for both playback and capture directions. For the monitor and impulse operations, still line6_pcm_acquire() and line6_pcm_release() are used. They call internally the corresponding functions for both playback and capture streams with proper lock or mutex. Unlike the previous versions, these function don't take the bit masks but the only single type value. Also they are supposed to be applied only as duplex operations. Tested-by: Chris Rorvick <chris@rorvick.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb/line6/toneport.c')
-rw-r--r--sound/usb/line6/toneport.c6
1 files changed, 3 insertions, 3 deletions
diff --git a/sound/usb/line6/toneport.c b/sound/usb/line6/toneport.c
index 33d16ecf18a0..61fa6256d7b0 100644
--- a/sound/usb/line6/toneport.c
+++ b/sound/usb/line6/toneport.c
@@ -189,9 +189,9 @@ static int snd_toneport_monitor_put(struct snd_kcontrol *kcontrol,
line6pcm->volume_monitor = ucontrol->value.integer.value[0];
if (line6pcm->volume_monitor > 0)
- line6_pcm_acquire(line6pcm, LINE6_BITS_PCM_MONITOR);
+ line6_pcm_acquire(line6pcm, LINE6_STREAM_MONITOR);
else
- line6_pcm_release(line6pcm, LINE6_BITS_PCM_MONITOR);
+ line6_pcm_release(line6pcm, LINE6_STREAM_MONITOR);
return 1;
}
@@ -252,7 +252,7 @@ static void toneport_start_pcm(unsigned long arg)
struct usb_line6_toneport *toneport = (struct usb_line6_toneport *)arg;
struct usb_line6 *line6 = &toneport->line6;
- line6_pcm_acquire(line6->line6pcm, LINE6_BITS_PCM_MONITOR);
+ line6_pcm_acquire(line6->line6pcm, LINE6_STREAM_MONITOR);
}
/* control definition */