summaryrefslogtreecommitdiffstats
path: root/sound/firewire/bebob
diff options
context:
space:
mode:
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>2015-02-21 09:54:57 -0500
committerTakashi Iwai <tiwai@suse.de>2015-02-23 03:10:38 -0500
commit12ed719291a953d443921f9cdb0ffee41066c340 (patch)
tree92362d30da81381fd8fe004fc3ba553ceea754ea /sound/firewire/bebob
parent6426460e5d87810e042962281fe3c1e8fc256162 (diff)
ALSA: fireworks/bebob/dice/oxfw: add reference-counting for FireWire unit
Fireworks and Dice drivers try to touch instances of FireWire unit after sound card object is released, while references to the unit is decremented in .remove(). When unplugging during streaming, sound card object is released after .remove(), thus Fireworks and Dice drivers causes GPF or Null-pointer-dereferencing to application processes because an instance of FireWire unit was already released. This commit adds reference-counting for FireWire unit in drivers to allow them to touch an instance of FireWire unit after .remove(). In most case, any operations after .remove() may be failed safely. 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/bebob')
-rw-r--r--sound/firewire/bebob/bebob.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c
index fc19c99654aa..b612599fb543 100644
--- a/sound/firewire/bebob/bebob.c
+++ b/sound/firewire/bebob/bebob.c
@@ -116,11 +116,19 @@ end:
116 return err; 116 return err;
117} 117}
118 118
119/*
120 * This module releases the FireWire unit data after all ALSA character devices
121 * are released by applications. This is for releasing stream data or finishing
122 * transactions safely. Thus at returning from .remove(), this module still keep
123 * references for the unit.
124 */
119static void 125static void
120bebob_card_free(struct snd_card *card) 126bebob_card_free(struct snd_card *card)
121{ 127{
122 struct snd_bebob *bebob = card->private_data; 128 struct snd_bebob *bebob = card->private_data;
123 129
130 fw_unit_put(bebob->unit);
131
124 if (bebob->card_index >= 0) { 132 if (bebob->card_index >= 0) {
125 mutex_lock(&devices_mutex); 133 mutex_lock(&devices_mutex);
126 clear_bit(bebob->card_index, devices_used); 134 clear_bit(bebob->card_index, devices_used);
@@ -205,7 +213,7 @@ bebob_probe(struct fw_unit *unit,
205 card->private_free = bebob_card_free; 213 card->private_free = bebob_card_free;
206 214
207 bebob->card = card; 215 bebob->card = card;
208 bebob->unit = unit; 216 bebob->unit = fw_unit_get(unit);
209 bebob->spec = spec; 217 bebob->spec = spec;
210 mutex_init(&bebob->mutex); 218 mutex_init(&bebob->mutex);
211 spin_lock_init(&bebob->lock); 219 spin_lock_init(&bebob->lock);
@@ -310,6 +318,8 @@ static void bebob_remove(struct fw_unit *unit)
310 318
311 snd_bebob_stream_destroy_duplex(bebob); 319 snd_bebob_stream_destroy_duplex(bebob);
312 snd_card_disconnect(bebob->card); 320 snd_card_disconnect(bebob->card);
321
322 /* No need to wait for releasing card object in this context. */
313 snd_card_free_when_closed(bebob->card); 323 snd_card_free_when_closed(bebob->card);
314} 324}
315 325