aboutsummaryrefslogtreecommitdiffstats
path: root/sound/firewire
diff options
context:
space:
mode:
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>2015-02-21 09:54:59 -0500
committerTakashi Iwai <tiwai@suse.de>2015-02-23 03:11:16 -0500
commitd23c2cc4485d10f0cedfef99dd2961d9652b1b3f (patch)
tree27c558371d511e9f93ef12c4d656fbb409fc087c /sound/firewire
parentc6f224dc20ad959175c2dfec70b5a61c6503a793 (diff)
ALSA: fireworks/bebob/dice/oxfw: allow stream destructor after releasing runtime
Currently stream destructor in each driver has a problem to be called in a context in which sound card object is released, because the destructors call amdtp_stream_pcm_abort() and touch PCM runtime data. The PCM runtime data is destroyed in application's context with snd_pcm_close(), on the other hand PCM substream data is destroyed after sound card object is released, in most case after all of ALSA character devices are released. When PCM runtime is destroyed and PCM substream is remained, amdtp_stream_pcm_abort() touches PCM runtime data and causes Null-pointer-dereference. This commit changes stream destructors and allows each driver to call it after releasing runtime. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Cc: <stable@vger.kernel.org> # 3.19+ Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/firewire')
-rw-r--r--sound/firewire/bebob/bebob_stream.c12
-rw-r--r--sound/firewire/dice/dice-stream.c18
-rw-r--r--sound/firewire/fireworks/fireworks_stream.c15
-rw-r--r--sound/firewire/oxfw/oxfw-stream.c6
4 files changed, 30 insertions, 21 deletions
diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c
index 0ebcabfdc7ce..fcca3eebc91f 100644
--- a/sound/firewire/bebob/bebob_stream.c
+++ b/sound/firewire/bebob/bebob_stream.c
@@ -410,8 +410,6 @@ break_both_connections(struct snd_bebob *bebob)
410static void 410static void
411destroy_both_connections(struct snd_bebob *bebob) 411destroy_both_connections(struct snd_bebob *bebob)
412{ 412{
413 break_both_connections(bebob);
414
415 cmp_connection_destroy(&bebob->in_conn); 413 cmp_connection_destroy(&bebob->in_conn);
416 cmp_connection_destroy(&bebob->out_conn); 414 cmp_connection_destroy(&bebob->out_conn);
417} 415}
@@ -712,16 +710,14 @@ void snd_bebob_stream_update_duplex(struct snd_bebob *bebob)
712 mutex_unlock(&bebob->mutex); 710 mutex_unlock(&bebob->mutex);
713} 711}
714 712
713/*
714 * This function should be called before starting streams or after stopping
715 * streams.
716 */
715void snd_bebob_stream_destroy_duplex(struct snd_bebob *bebob) 717void snd_bebob_stream_destroy_duplex(struct snd_bebob *bebob)
716{ 718{
717 mutex_lock(&bebob->mutex); 719 mutex_lock(&bebob->mutex);
718 720
719 amdtp_stream_pcm_abort(&bebob->rx_stream);
720 amdtp_stream_pcm_abort(&bebob->tx_stream);
721
722 amdtp_stream_stop(&bebob->rx_stream);
723 amdtp_stream_stop(&bebob->tx_stream);
724
725 amdtp_stream_destroy(&bebob->rx_stream); 721 amdtp_stream_destroy(&bebob->rx_stream);
726 amdtp_stream_destroy(&bebob->tx_stream); 722 amdtp_stream_destroy(&bebob->tx_stream);
727 723
diff --git a/sound/firewire/dice/dice-stream.c b/sound/firewire/dice/dice-stream.c
index fa9cf761b610..07dbd01d7a6b 100644
--- a/sound/firewire/dice/dice-stream.c
+++ b/sound/firewire/dice/dice-stream.c
@@ -311,14 +311,21 @@ end:
311 return err; 311 return err;
312} 312}
313 313
314/*
315 * This function should be called before starting streams or after stopping
316 * streams.
317 */
314static void destroy_stream(struct snd_dice *dice, struct amdtp_stream *stream) 318static void destroy_stream(struct snd_dice *dice, struct amdtp_stream *stream)
315{ 319{
316 amdtp_stream_destroy(stream); 320 struct fw_iso_resources *resources;
317 321
318 if (stream == &dice->tx_stream) 322 if (stream == &dice->tx_stream)
319 fw_iso_resources_destroy(&dice->tx_resources); 323 resources = &dice->tx_resources;
320 else 324 else
321 fw_iso_resources_destroy(&dice->rx_resources); 325 resources = &dice->rx_resources;
326
327 amdtp_stream_destroy(stream);
328 fw_iso_resources_destroy(resources);
322} 329}
323 330
324int snd_dice_stream_init_duplex(struct snd_dice *dice) 331int snd_dice_stream_init_duplex(struct snd_dice *dice)
@@ -332,6 +339,8 @@ int snd_dice_stream_init_duplex(struct snd_dice *dice)
332 goto end; 339 goto end;
333 340
334 err = init_stream(dice, &dice->rx_stream); 341 err = init_stream(dice, &dice->rx_stream);
342 if (err < 0)
343 destroy_stream(dice, &dice->tx_stream);
335end: 344end:
336 return err; 345 return err;
337} 346}
@@ -340,10 +349,7 @@ void snd_dice_stream_destroy_duplex(struct snd_dice *dice)
340{ 349{
341 snd_dice_transaction_clear_enable(dice); 350 snd_dice_transaction_clear_enable(dice);
342 351
343 stop_stream(dice, &dice->tx_stream);
344 destroy_stream(dice, &dice->tx_stream); 352 destroy_stream(dice, &dice->tx_stream);
345
346 stop_stream(dice, &dice->rx_stream);
347 destroy_stream(dice, &dice->rx_stream); 353 destroy_stream(dice, &dice->rx_stream);
348 354
349 dice->substreams_counter = 0; 355 dice->substreams_counter = 0;
diff --git a/sound/firewire/fireworks/fireworks_stream.c b/sound/firewire/fireworks/fireworks_stream.c
index 4f440e163667..f817b7ae097e 100644
--- a/sound/firewire/fireworks/fireworks_stream.c
+++ b/sound/firewire/fireworks/fireworks_stream.c
@@ -100,17 +100,22 @@ end:
100 return err; 100 return err;
101} 101}
102 102
103/*
104 * This function should be called before starting the stream or after stopping
105 * the streams.
106 */
103static void 107static void
104destroy_stream(struct snd_efw *efw, struct amdtp_stream *stream) 108destroy_stream(struct snd_efw *efw, struct amdtp_stream *stream)
105{ 109{
106 stop_stream(efw, stream); 110 struct cmp_connection *conn;
107
108 amdtp_stream_destroy(stream);
109 111
110 if (stream == &efw->tx_stream) 112 if (stream == &efw->tx_stream)
111 cmp_connection_destroy(&efw->out_conn); 113 conn = &efw->out_conn;
112 else 114 else
113 cmp_connection_destroy(&efw->in_conn); 115 conn = &efw->in_conn;
116
117 amdtp_stream_destroy(stream);
118 cmp_connection_destroy(&efw->out_conn);
114} 119}
115 120
116static int 121static int
diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c
index bda845afb470..29ccb3637164 100644
--- a/sound/firewire/oxfw/oxfw-stream.c
+++ b/sound/firewire/oxfw/oxfw-stream.c
@@ -337,6 +337,10 @@ void snd_oxfw_stream_stop_simplex(struct snd_oxfw *oxfw,
337 stop_stream(oxfw, stream); 337 stop_stream(oxfw, stream);
338} 338}
339 339
340/*
341 * This function should be called before starting the stream or after stopping
342 * the streams.
343 */
340void snd_oxfw_stream_destroy_simplex(struct snd_oxfw *oxfw, 344void snd_oxfw_stream_destroy_simplex(struct snd_oxfw *oxfw,
341 struct amdtp_stream *stream) 345 struct amdtp_stream *stream)
342{ 346{
@@ -347,8 +351,6 @@ void snd_oxfw_stream_destroy_simplex(struct snd_oxfw *oxfw,
347 else 351 else
348 conn = &oxfw->in_conn; 352 conn = &oxfw->in_conn;
349 353
350 stop_stream(oxfw, stream);
351
352 amdtp_stream_destroy(stream); 354 amdtp_stream_destroy(stream);
353 cmp_connection_destroy(conn); 355 cmp_connection_destroy(conn);
354} 356}