| .. | .. | 
|---|
|  | 1 | +// SPDX-License-Identifier: GPL-2.0-only | 
|---|
| 1 | 2 | /* | 
|---|
| 2 | 3 | * tascam.c - a part of driver for TASCAM FireWire series | 
|---|
| 3 | 4 | * | 
|---|
| 4 | 5 | * Copyright (c) 2015 Takashi Sakamoto | 
|---|
| 5 |  | - * | 
|---|
| 6 |  | - * Licensed under the terms of the GNU General Public License, version 2. | 
|---|
| 7 | 6 | */ | 
|---|
| 8 | 7 |  | 
|---|
| 9 | 8 | #include "tascam.h" | 
|---|
| .. | .. | 
|---|
| 85 | 84 | return 0; | 
|---|
| 86 | 85 | } | 
|---|
| 87 | 86 |  | 
|---|
| 88 |  | -static void tscm_free(struct snd_tscm *tscm) | 
|---|
| 89 |  | -{ | 
|---|
| 90 |  | -	snd_tscm_transaction_unregister(tscm); | 
|---|
| 91 |  | -	snd_tscm_stream_destroy_duplex(tscm); | 
|---|
| 92 |  | - | 
|---|
| 93 |  | -	fw_unit_put(tscm->unit); | 
|---|
| 94 |  | - | 
|---|
| 95 |  | -	mutex_destroy(&tscm->mutex); | 
|---|
| 96 |  | -	kfree(tscm); | 
|---|
| 97 |  | -} | 
|---|
| 98 |  | - | 
|---|
| 99 | 87 | static void tscm_card_free(struct snd_card *card) | 
|---|
| 100 | 88 | { | 
|---|
| 101 |  | -	tscm_free(card->private_data); | 
|---|
|  | 89 | +	struct snd_tscm *tscm = card->private_data; | 
|---|
|  | 90 | + | 
|---|
|  | 91 | +	snd_tscm_transaction_unregister(tscm); | 
|---|
|  | 92 | +	snd_tscm_stream_destroy_duplex(tscm); | 
|---|
| 102 | 93 | } | 
|---|
| 103 | 94 |  | 
|---|
| 104 | 95 | static void do_registration(struct work_struct *work) | 
|---|
| .. | .. | 
|---|
| 110 | 101 | &tscm->card); | 
|---|
| 111 | 102 | if (err < 0) | 
|---|
| 112 | 103 | return; | 
|---|
|  | 104 | +	tscm->card->private_free = tscm_card_free; | 
|---|
|  | 105 | +	tscm->card->private_data = tscm; | 
|---|
| 113 | 106 |  | 
|---|
| 114 | 107 | err = identify_model(tscm); | 
|---|
| 115 | 108 | if (err < 0) | 
|---|
| .. | .. | 
|---|
| 141 | 134 | if (err < 0) | 
|---|
| 142 | 135 | goto error; | 
|---|
| 143 | 136 |  | 
|---|
| 144 |  | -	/* | 
|---|
| 145 |  | -	 * After registered, tscm instance can be released corresponding to | 
|---|
| 146 |  | -	 * releasing the sound card instance. | 
|---|
| 147 |  | -	 */ | 
|---|
| 148 |  | -	tscm->card->private_free = tscm_card_free; | 
|---|
| 149 |  | -	tscm->card->private_data = tscm; | 
|---|
| 150 | 137 | tscm->registered = true; | 
|---|
| 151 | 138 |  | 
|---|
| 152 | 139 | return; | 
|---|
| 153 | 140 | error: | 
|---|
| 154 |  | -	snd_tscm_transaction_unregister(tscm); | 
|---|
| 155 |  | -	snd_tscm_stream_destroy_duplex(tscm); | 
|---|
| 156 | 141 | snd_card_free(tscm->card); | 
|---|
| 157 | 142 | dev_info(&tscm->unit->device, | 
|---|
| 158 | 143 | "Sound card registration failed: %d\n", err); | 
|---|
| .. | .. | 
|---|
| 164 | 149 | struct snd_tscm *tscm; | 
|---|
| 165 | 150 |  | 
|---|
| 166 | 151 | /* Allocate this independent of sound card instance. */ | 
|---|
| 167 |  | -	tscm = kzalloc(sizeof(struct snd_tscm), GFP_KERNEL); | 
|---|
| 168 |  | -	if (tscm == NULL) | 
|---|
|  | 152 | +	tscm = devm_kzalloc(&unit->device, sizeof(struct snd_tscm), GFP_KERNEL); | 
|---|
|  | 153 | +	if (!tscm) | 
|---|
| 169 | 154 | return -ENOMEM; | 
|---|
| 170 |  | - | 
|---|
| 171 |  | -	/* initialize myself */ | 
|---|
| 172 | 155 | tscm->unit = fw_unit_get(unit); | 
|---|
| 173 | 156 | dev_set_drvdata(&unit->device, tscm); | 
|---|
| 174 | 157 |  | 
|---|
| .. | .. | 
|---|
| 216 | 199 | cancel_delayed_work_sync(&tscm->dwork); | 
|---|
| 217 | 200 |  | 
|---|
| 218 | 201 | if (tscm->registered) { | 
|---|
| 219 |  | -		/* No need to wait for releasing card object in this context. */ | 
|---|
| 220 |  | -		snd_card_free_when_closed(tscm->card); | 
|---|
| 221 |  | -	} else { | 
|---|
| 222 |  | -		/* Don't forget this case. */ | 
|---|
| 223 |  | -		tscm_free(tscm); | 
|---|
|  | 202 | +		// Block till all of ALSA character devices are released. | 
|---|
|  | 203 | +		snd_card_free(tscm->card); | 
|---|
| 224 | 204 | } | 
|---|
|  | 205 | + | 
|---|
|  | 206 | +	mutex_destroy(&tscm->mutex); | 
|---|
|  | 207 | +	fw_unit_put(tscm->unit); | 
|---|
| 225 | 208 | } | 
|---|
| 226 | 209 |  | 
|---|
| 227 | 210 | static const struct ieee1394_device_id snd_tscm_id_table[] = { | 
|---|
| .. | .. | 
|---|
| 259 | 242 | .specifier_id = 0x00022e, | 
|---|
| 260 | 243 | .version = 0x800004, | 
|---|
| 261 | 244 | }, | 
|---|
| 262 |  | -	/* FE-08 requires reverse-engineering because it just has faders. */ | 
|---|
| 263 | 245 | {} | 
|---|
| 264 | 246 | }; | 
|---|
| 265 | 247 | MODULE_DEVICE_TABLE(ieee1394, snd_tscm_id_table); | 
|---|
| .. | .. | 
|---|
| 267 | 249 | static struct fw_driver tscm_driver = { | 
|---|
| 268 | 250 | .driver = { | 
|---|
| 269 | 251 | .owner = THIS_MODULE, | 
|---|
| 270 |  | -		.name = "snd-firewire-tascam", | 
|---|
|  | 252 | +		.name = KBUILD_MODNAME, | 
|---|
| 271 | 253 | .bus = &fw_bus_type, | 
|---|
| 272 | 254 | }, | 
|---|
| 273 | 255 | .probe    = snd_tscm_probe, | 
|---|