diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2011-05-11 04:47:30 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-05-11 08:51:09 -0400 |
commit | 03c29680d49662859d14d64f8673550fa3fb2ed1 (patch) | |
tree | 0b072dfc7de12605bfa3106c45566b7cc98462fb /sound/firewire/isight.c | |
parent | 3a691b28a0ca3cf4d9010c6158318159e0275d2c (diff) |
ALSA: isight: fix isight_pcm_abort() crashes
Fix crashes in isight_pcm_abort() that happen when the driver tries to
access isight->pcm->runtime which does not exist when the device is not
open. Introduce a new field pcm_active to track this state.
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Reported-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/firewire/isight.c')
-rw-r--r-- | sound/firewire/isight.c | 26 |
1 files changed, 20 insertions, 6 deletions
diff --git a/sound/firewire/isight.c b/sound/firewire/isight.c index a6f19f57a1c3..0230605c917e 100644 --- a/sound/firewire/isight.c +++ b/sound/firewire/isight.c | |||
@@ -56,6 +56,7 @@ struct isight { | |||
56 | struct iso_packets_buffer buffer; | 56 | struct iso_packets_buffer buffer; |
57 | struct fw_iso_resources resources; | 57 | struct fw_iso_resources resources; |
58 | struct fw_iso_context *context; | 58 | struct fw_iso_context *context; |
59 | bool pcm_active; | ||
59 | bool pcm_running; | 60 | bool pcm_running; |
60 | bool first_packet; | 61 | bool first_packet; |
61 | int packet_index; | 62 | int packet_index; |
@@ -131,10 +132,12 @@ static void isight_pcm_abort(struct isight *isight) | |||
131 | { | 132 | { |
132 | unsigned long flags; | 133 | unsigned long flags; |
133 | 134 | ||
134 | snd_pcm_stream_lock_irqsave(isight->pcm, flags); | 135 | if (ACCESS_ONCE(isight->pcm_active)) { |
135 | if (snd_pcm_running(isight->pcm)) | 136 | snd_pcm_stream_lock_irqsave(isight->pcm, flags); |
136 | snd_pcm_stop(isight->pcm, SNDRV_PCM_STATE_XRUN); | 137 | if (snd_pcm_running(isight->pcm)) |
137 | snd_pcm_stream_unlock_irqrestore(isight->pcm, flags); | 138 | snd_pcm_stop(isight->pcm, SNDRV_PCM_STATE_XRUN); |
139 | snd_pcm_stream_unlock_irqrestore(isight->pcm, flags); | ||
140 | } | ||
138 | } | 141 | } |
139 | 142 | ||
140 | static void isight_dropped_samples(struct isight *isight, unsigned int total) | 143 | static void isight_dropped_samples(struct isight *isight, unsigned int total) |
@@ -295,8 +298,17 @@ static int isight_close(struct snd_pcm_substream *substream) | |||
295 | static int isight_hw_params(struct snd_pcm_substream *substream, | 298 | static int isight_hw_params(struct snd_pcm_substream *substream, |
296 | struct snd_pcm_hw_params *hw_params) | 299 | struct snd_pcm_hw_params *hw_params) |
297 | { | 300 | { |
298 | return snd_pcm_lib_alloc_vmalloc_buffer(substream, | 301 | struct isight *isight = substream->private_data; |
299 | params_buffer_bytes(hw_params)); | 302 | int err; |
303 | |||
304 | err = snd_pcm_lib_alloc_vmalloc_buffer(substream, | ||
305 | params_buffer_bytes(hw_params)); | ||
306 | if (err < 0) | ||
307 | return err; | ||
308 | |||
309 | ACCESS_ONCE(isight->pcm_active) = true; | ||
310 | |||
311 | return 0; | ||
300 | } | 312 | } |
301 | 313 | ||
302 | static void isight_stop_streaming(struct isight *isight) | 314 | static void isight_stop_streaming(struct isight *isight) |
@@ -322,6 +334,8 @@ static int isight_hw_free(struct snd_pcm_substream *substream) | |||
322 | { | 334 | { |
323 | struct isight *isight = substream->private_data; | 335 | struct isight *isight = substream->private_data; |
324 | 336 | ||
337 | ACCESS_ONCE(isight->pcm_active) = false; | ||
338 | |||
325 | mutex_lock(&isight->mutex); | 339 | mutex_lock(&isight->mutex); |
326 | isight_stop_streaming(isight); | 340 | isight_stop_streaming(isight); |
327 | mutex_unlock(&isight->mutex); | 341 | mutex_unlock(&isight->mutex); |