diff options
-rw-r--r-- | sound/firewire/bebob/bebob_stream.c | 30 | ||||
-rw-r--r-- | sound/firewire/cmp.c | 74 | ||||
-rw-r--r-- | sound/firewire/cmp.h | 7 | ||||
-rw-r--r-- | sound/firewire/fireworks/fireworks_stream.c | 22 | ||||
-rw-r--r-- | sound/firewire/oxfw/oxfw-stream.c | 18 |
5 files changed, 100 insertions, 51 deletions
diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c index 9ef4663d13e5..1070a675179d 100644 --- a/sound/firewire/bebob/bebob_stream.c +++ b/sound/firewire/bebob/bebob_stream.c | |||
@@ -404,13 +404,11 @@ static int make_both_connections(struct snd_bebob *bebob) | |||
404 | { | 404 | { |
405 | int err = 0; | 405 | int err = 0; |
406 | 406 | ||
407 | err = cmp_connection_establish(&bebob->out_conn, | 407 | err = cmp_connection_establish(&bebob->out_conn); |
408 | amdtp_stream_get_max_payload(&bebob->tx_stream)); | ||
409 | if (err < 0) | 408 | if (err < 0) |
410 | return err; | 409 | return err; |
411 | 410 | ||
412 | err = cmp_connection_establish(&bebob->in_conn, | 411 | err = cmp_connection_establish(&bebob->in_conn); |
413 | amdtp_stream_get_max_payload(&bebob->rx_stream)); | ||
414 | if (err < 0) { | 412 | if (err < 0) { |
415 | cmp_connection_break(&bebob->out_conn); | 413 | cmp_connection_break(&bebob->out_conn); |
416 | return err; | 414 | return err; |
@@ -533,14 +531,23 @@ static int keep_resources(struct snd_bebob *bebob, struct amdtp_stream *stream, | |||
533 | unsigned int rate, unsigned int index) | 531 | unsigned int rate, unsigned int index) |
534 | { | 532 | { |
535 | struct snd_bebob_stream_formation *formation; | 533 | struct snd_bebob_stream_formation *formation; |
534 | struct cmp_connection *conn; | ||
535 | int err; | ||
536 | 536 | ||
537 | if (stream == &bebob->tx_stream) | 537 | if (stream == &bebob->tx_stream) { |
538 | formation = bebob->tx_stream_formations + index; | 538 | formation = bebob->tx_stream_formations + index; |
539 | else | 539 | conn = &bebob->out_conn; |
540 | } else { | ||
540 | formation = bebob->rx_stream_formations + index; | 541 | formation = bebob->rx_stream_formations + index; |
542 | conn = &bebob->in_conn; | ||
543 | } | ||
544 | |||
545 | err = amdtp_am824_set_parameters(stream, rate, formation->pcm, | ||
546 | formation->midi, false); | ||
547 | if (err < 0) | ||
548 | return err; | ||
541 | 549 | ||
542 | return amdtp_am824_set_parameters(stream, rate, formation->pcm, | 550 | return cmp_connection_reserve(conn, amdtp_stream_get_max_payload(stream)); |
543 | formation->midi, false); | ||
544 | } | 551 | } |
545 | 552 | ||
546 | int snd_bebob_stream_reserve_duplex(struct snd_bebob *bebob, unsigned int rate) | 553 | int snd_bebob_stream_reserve_duplex(struct snd_bebob *bebob, unsigned int rate) |
@@ -591,8 +598,10 @@ int snd_bebob_stream_reserve_duplex(struct snd_bebob *bebob, unsigned int rate) | |||
591 | return err; | 598 | return err; |
592 | 599 | ||
593 | err = keep_resources(bebob, &bebob->rx_stream, rate, index); | 600 | err = keep_resources(bebob, &bebob->rx_stream, rate, index); |
594 | if (err < 0) | 601 | if (err < 0) { |
602 | cmp_connection_release(&bebob->out_conn); | ||
595 | return err; | 603 | return err; |
604 | } | ||
596 | } | 605 | } |
597 | 606 | ||
598 | return 0; | 607 | return 0; |
@@ -685,6 +694,9 @@ void snd_bebob_stream_stop_duplex(struct snd_bebob *bebob) | |||
685 | amdtp_stream_stop(&bebob->tx_stream); | 694 | amdtp_stream_stop(&bebob->tx_stream); |
686 | 695 | ||
687 | break_both_connections(bebob); | 696 | break_both_connections(bebob); |
697 | |||
698 | cmp_connection_release(&bebob->out_conn); | ||
699 | cmp_connection_release(&bebob->in_conn); | ||
688 | } | 700 | } |
689 | } | 701 | } |
690 | 702 | ||
diff --git a/sound/firewire/cmp.c b/sound/firewire/cmp.c index ae3bc1940efa..5dedc4f31842 100644 --- a/sound/firewire/cmp.c +++ b/sound/firewire/cmp.c | |||
@@ -185,6 +185,37 @@ void cmp_connection_destroy(struct cmp_connection *c) | |||
185 | } | 185 | } |
186 | EXPORT_SYMBOL(cmp_connection_destroy); | 186 | EXPORT_SYMBOL(cmp_connection_destroy); |
187 | 187 | ||
188 | int cmp_connection_reserve(struct cmp_connection *c, | ||
189 | unsigned int max_payload_bytes) | ||
190 | { | ||
191 | int err; | ||
192 | |||
193 | mutex_lock(&c->mutex); | ||
194 | |||
195 | if (WARN_ON(c->resources.allocated)) { | ||
196 | err = -EBUSY; | ||
197 | goto end; | ||
198 | } | ||
199 | |||
200 | c->speed = min(c->max_speed, | ||
201 | fw_parent_device(c->resources.unit)->max_speed); | ||
202 | |||
203 | err = fw_iso_resources_allocate(&c->resources, max_payload_bytes, | ||
204 | c->speed); | ||
205 | end: | ||
206 | mutex_unlock(&c->mutex); | ||
207 | |||
208 | return err; | ||
209 | } | ||
210 | EXPORT_SYMBOL(cmp_connection_reserve); | ||
211 | |||
212 | void cmp_connection_release(struct cmp_connection *c) | ||
213 | { | ||
214 | mutex_lock(&c->mutex); | ||
215 | fw_iso_resources_free(&c->resources); | ||
216 | mutex_unlock(&c->mutex); | ||
217 | } | ||
218 | EXPORT_SYMBOL(cmp_connection_release); | ||
188 | 219 | ||
189 | static __be32 ipcr_set_modify(struct cmp_connection *c, __be32 ipcr) | 220 | static __be32 ipcr_set_modify(struct cmp_connection *c, __be32 ipcr) |
190 | { | 221 | { |
@@ -270,25 +301,18 @@ static int pcr_set_check(struct cmp_connection *c, __be32 pcr) | |||
270 | * When this function succeeds, the caller is responsible for starting | 301 | * When this function succeeds, the caller is responsible for starting |
271 | * transmitting packets. | 302 | * transmitting packets. |
272 | */ | 303 | */ |
273 | int cmp_connection_establish(struct cmp_connection *c, | 304 | int cmp_connection_establish(struct cmp_connection *c) |
274 | unsigned int max_payload_bytes) | ||
275 | { | 305 | { |
276 | int err; | 306 | int err; |
277 | 307 | ||
278 | if (WARN_ON(c->connected)) | ||
279 | return -EISCONN; | ||
280 | |||
281 | c->speed = min(c->max_speed, | ||
282 | fw_parent_device(c->resources.unit)->max_speed); | ||
283 | |||
284 | mutex_lock(&c->mutex); | 308 | mutex_lock(&c->mutex); |
285 | 309 | ||
286 | retry_after_bus_reset: | 310 | if (WARN_ON(c->connected)) { |
287 | err = fw_iso_resources_allocate(&c->resources, | 311 | mutex_unlock(&c->mutex); |
288 | max_payload_bytes, c->speed); | 312 | return -EISCONN; |
289 | if (err < 0) | 313 | } |
290 | goto err_mutex; | ||
291 | 314 | ||
315 | retry_after_bus_reset: | ||
292 | if (c->direction == CMP_OUTPUT) | 316 | if (c->direction == CMP_OUTPUT) |
293 | err = pcr_modify(c, opcr_set_modify, pcr_set_check, | 317 | err = pcr_modify(c, opcr_set_modify, pcr_set_check, |
294 | ABORT_ON_BUS_RESET); | 318 | ABORT_ON_BUS_RESET); |
@@ -297,21 +321,13 @@ retry_after_bus_reset: | |||
297 | ABORT_ON_BUS_RESET); | 321 | ABORT_ON_BUS_RESET); |
298 | 322 | ||
299 | if (err == -EAGAIN) { | 323 | if (err == -EAGAIN) { |
300 | fw_iso_resources_free(&c->resources); | 324 | err = fw_iso_resources_update(&c->resources); |
301 | goto retry_after_bus_reset; | 325 | if (err >= 0) |
326 | goto retry_after_bus_reset; | ||
302 | } | 327 | } |
303 | if (err < 0) | 328 | if (err >= 0) |
304 | goto err_resources; | 329 | c->connected = true; |
305 | |||
306 | c->connected = true; | ||
307 | |||
308 | mutex_unlock(&c->mutex); | ||
309 | |||
310 | return 0; | ||
311 | 330 | ||
312 | err_resources: | ||
313 | fw_iso_resources_free(&c->resources); | ||
314 | err_mutex: | ||
315 | mutex_unlock(&c->mutex); | 331 | mutex_unlock(&c->mutex); |
316 | 332 | ||
317 | return err; | 333 | return err; |
@@ -351,14 +367,12 @@ int cmp_connection_update(struct cmp_connection *c) | |||
351 | SUCCEED_ON_BUS_RESET); | 367 | SUCCEED_ON_BUS_RESET); |
352 | 368 | ||
353 | if (err < 0) | 369 | if (err < 0) |
354 | goto err_resources; | 370 | goto err_unconnect; |
355 | 371 | ||
356 | mutex_unlock(&c->mutex); | 372 | mutex_unlock(&c->mutex); |
357 | 373 | ||
358 | return 0; | 374 | return 0; |
359 | 375 | ||
360 | err_resources: | ||
361 | fw_iso_resources_free(&c->resources); | ||
362 | err_unconnect: | 376 | err_unconnect: |
363 | c->connected = false; | 377 | c->connected = false; |
364 | mutex_unlock(&c->mutex); | 378 | mutex_unlock(&c->mutex); |
@@ -395,8 +409,6 @@ void cmp_connection_break(struct cmp_connection *c) | |||
395 | if (err < 0) | 409 | if (err < 0) |
396 | cmp_error(c, "plug is still connected\n"); | 410 | cmp_error(c, "plug is still connected\n"); |
397 | 411 | ||
398 | fw_iso_resources_free(&c->resources); | ||
399 | |||
400 | c->connected = false; | 412 | c->connected = false; |
401 | 413 | ||
402 | mutex_unlock(&c->mutex); | 414 | mutex_unlock(&c->mutex); |
diff --git a/sound/firewire/cmp.h b/sound/firewire/cmp.h index b60b415caa8f..26ab88000e34 100644 --- a/sound/firewire/cmp.h +++ b/sound/firewire/cmp.h | |||
@@ -42,8 +42,11 @@ int cmp_connection_init(struct cmp_connection *connection, | |||
42 | int cmp_connection_check_used(struct cmp_connection *connection, bool *used); | 42 | int cmp_connection_check_used(struct cmp_connection *connection, bool *used); |
43 | void cmp_connection_destroy(struct cmp_connection *connection); | 43 | void cmp_connection_destroy(struct cmp_connection *connection); |
44 | 44 | ||
45 | int cmp_connection_establish(struct cmp_connection *connection, | 45 | int cmp_connection_reserve(struct cmp_connection *connection, |
46 | unsigned int max_payload); | 46 | unsigned int max_payload); |
47 | void cmp_connection_release(struct cmp_connection *connection); | ||
48 | |||
49 | int cmp_connection_establish(struct cmp_connection *connection); | ||
47 | int cmp_connection_update(struct cmp_connection *connection); | 50 | int cmp_connection_update(struct cmp_connection *connection); |
48 | void cmp_connection_break(struct cmp_connection *connection); | 51 | void cmp_connection_break(struct cmp_connection *connection); |
49 | 52 | ||
diff --git a/sound/firewire/fireworks/fireworks_stream.c b/sound/firewire/fireworks/fireworks_stream.c index 61342c49dc38..81c1bb209a89 100644 --- a/sound/firewire/fireworks/fireworks_stream.c +++ b/sound/firewire/fireworks/fireworks_stream.c | |||
@@ -63,8 +63,7 @@ static int start_stream(struct snd_efw *efw, struct amdtp_stream *stream, | |||
63 | conn = &efw->in_conn; | 63 | conn = &efw->in_conn; |
64 | 64 | ||
65 | // Establish connection via CMP. | 65 | // Establish connection via CMP. |
66 | err = cmp_connection_establish(conn, | 66 | err = cmp_connection_establish(conn); |
67 | amdtp_stream_get_max_payload(stream)); | ||
68 | if (err < 0) | 67 | if (err < 0) |
69 | return err; | 68 | return err; |
70 | 69 | ||
@@ -177,17 +176,25 @@ static int keep_resources(struct snd_efw *efw, struct amdtp_stream *stream, | |||
177 | { | 176 | { |
178 | unsigned int pcm_channels; | 177 | unsigned int pcm_channels; |
179 | unsigned int midi_ports; | 178 | unsigned int midi_ports; |
179 | struct cmp_connection *conn; | ||
180 | int err; | ||
180 | 181 | ||
181 | if (stream == &efw->tx_stream) { | 182 | if (stream == &efw->tx_stream) { |
182 | pcm_channels = efw->pcm_capture_channels[mode]; | 183 | pcm_channels = efw->pcm_capture_channels[mode]; |
183 | midi_ports = efw->midi_out_ports; | 184 | midi_ports = efw->midi_out_ports; |
185 | conn = &efw->out_conn; | ||
184 | } else { | 186 | } else { |
185 | pcm_channels = efw->pcm_playback_channels[mode]; | 187 | pcm_channels = efw->pcm_playback_channels[mode]; |
186 | midi_ports = efw->midi_in_ports; | 188 | midi_ports = efw->midi_in_ports; |
189 | conn = &efw->in_conn; | ||
187 | } | 190 | } |
188 | 191 | ||
189 | return amdtp_am824_set_parameters(stream, rate, pcm_channels, | 192 | err = amdtp_am824_set_parameters(stream, rate, pcm_channels, |
190 | midi_ports, false); | 193 | midi_ports, false); |
194 | if (err < 0) | ||
195 | return err; | ||
196 | |||
197 | return cmp_connection_reserve(conn, amdtp_stream_get_max_payload(stream)); | ||
191 | } | 198 | } |
192 | 199 | ||
193 | int snd_efw_stream_reserve_duplex(struct snd_efw *efw, unsigned int rate) | 200 | int snd_efw_stream_reserve_duplex(struct snd_efw *efw, unsigned int rate) |
@@ -228,8 +235,10 @@ int snd_efw_stream_reserve_duplex(struct snd_efw *efw, unsigned int rate) | |||
228 | return err; | 235 | return err; |
229 | 236 | ||
230 | err = keep_resources(efw, &efw->rx_stream, rate, mode); | 237 | err = keep_resources(efw, &efw->rx_stream, rate, mode); |
231 | if (err < 0) | 238 | if (err < 0) { |
239 | cmp_connection_release(&efw->in_conn); | ||
232 | return err; | 240 | return err; |
241 | } | ||
233 | } | 242 | } |
234 | 243 | ||
235 | return 0; | 244 | return 0; |
@@ -285,6 +294,9 @@ void snd_efw_stream_stop_duplex(struct snd_efw *efw) | |||
285 | if (efw->substreams_counter == 0) { | 294 | if (efw->substreams_counter == 0) { |
286 | stop_stream(efw, &efw->tx_stream); | 295 | stop_stream(efw, &efw->tx_stream); |
287 | stop_stream(efw, &efw->rx_stream); | 296 | stop_stream(efw, &efw->rx_stream); |
297 | |||
298 | cmp_connection_release(&efw->out_conn); | ||
299 | cmp_connection_release(&efw->in_conn); | ||
288 | } | 300 | } |
289 | } | 301 | } |
290 | 302 | ||
diff --git a/sound/firewire/oxfw/oxfw-stream.c b/sound/firewire/oxfw/oxfw-stream.c index 837733f10736..a8bc798731ff 100644 --- a/sound/firewire/oxfw/oxfw-stream.c +++ b/sound/firewire/oxfw/oxfw-stream.c | |||
@@ -111,8 +111,7 @@ static int start_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream) | |||
111 | else | 111 | else |
112 | conn = &oxfw->out_conn; | 112 | conn = &oxfw->out_conn; |
113 | 113 | ||
114 | err = cmp_connection_establish(conn, | 114 | err = cmp_connection_establish(conn); |
115 | amdtp_stream_get_max_payload(stream)); | ||
116 | if (err < 0) | 115 | if (err < 0) |
117 | return err; | 116 | return err; |
118 | 117 | ||
@@ -203,15 +202,18 @@ static int keep_resources(struct snd_oxfw *oxfw, struct amdtp_stream *stream) | |||
203 | enum avc_general_plug_dir dir; | 202 | enum avc_general_plug_dir dir; |
204 | u8 **formats; | 203 | u8 **formats; |
205 | struct snd_oxfw_stream_formation formation; | 204 | struct snd_oxfw_stream_formation formation; |
205 | struct cmp_connection *conn; | ||
206 | int i; | 206 | int i; |
207 | int err; | 207 | int err; |
208 | 208 | ||
209 | if (stream == &oxfw->rx_stream) { | 209 | if (stream == &oxfw->rx_stream) { |
210 | dir = AVC_GENERAL_PLUG_DIR_IN; | 210 | dir = AVC_GENERAL_PLUG_DIR_IN; |
211 | formats = oxfw->rx_stream_formats; | 211 | formats = oxfw->rx_stream_formats; |
212 | conn = &oxfw->in_conn; | ||
212 | } else { | 213 | } else { |
213 | dir = AVC_GENERAL_PLUG_DIR_OUT; | 214 | dir = AVC_GENERAL_PLUG_DIR_OUT; |
214 | formats = oxfw->tx_stream_formats; | 215 | formats = oxfw->tx_stream_formats; |
216 | conn = &oxfw->out_conn; | ||
215 | } | 217 | } |
216 | 218 | ||
217 | err = snd_oxfw_stream_get_current_formation(oxfw, dir, &formation); | 219 | err = snd_oxfw_stream_get_current_formation(oxfw, dir, &formation); |
@@ -239,8 +241,12 @@ static int keep_resources(struct snd_oxfw *oxfw, struct amdtp_stream *stream) | |||
239 | if (formation.pcm == 0) | 241 | if (formation.pcm == 0) |
240 | return -EINVAL; | 242 | return -EINVAL; |
241 | 243 | ||
242 | return amdtp_am824_set_parameters(stream, formation.rate, formation.pcm, | 244 | err = amdtp_am824_set_parameters(stream, formation.rate, formation.pcm, |
243 | formation.midi * 8, false); | 245 | formation.midi * 8, false); |
246 | if (err < 0) | ||
247 | return err; | ||
248 | |||
249 | return cmp_connection_reserve(conn, amdtp_stream_get_max_payload(stream)); | ||
244 | } | 250 | } |
245 | 251 | ||
246 | int snd_oxfw_stream_reserve_duplex(struct snd_oxfw *oxfw, | 252 | int snd_oxfw_stream_reserve_duplex(struct snd_oxfw *oxfw, |
@@ -299,8 +305,10 @@ int snd_oxfw_stream_reserve_duplex(struct snd_oxfw *oxfw, | |||
299 | 305 | ||
300 | if (oxfw->has_output) { | 306 | if (oxfw->has_output) { |
301 | err = keep_resources(oxfw, &oxfw->tx_stream); | 307 | err = keep_resources(oxfw, &oxfw->tx_stream); |
302 | if (err < 0) | 308 | if (err < 0) { |
309 | cmp_connection_release(&oxfw->in_conn); | ||
303 | return err; | 310 | return err; |
311 | } | ||
304 | } | 312 | } |
305 | } | 313 | } |
306 | 314 | ||
@@ -361,10 +369,12 @@ void snd_oxfw_stream_stop_duplex(struct snd_oxfw *oxfw) | |||
361 | if (oxfw->substreams_count == 0) { | 369 | if (oxfw->substreams_count == 0) { |
362 | amdtp_stream_stop(&oxfw->rx_stream); | 370 | amdtp_stream_stop(&oxfw->rx_stream); |
363 | cmp_connection_break(&oxfw->in_conn); | 371 | cmp_connection_break(&oxfw->in_conn); |
372 | cmp_connection_release(&oxfw->in_conn); | ||
364 | 373 | ||
365 | if (oxfw->has_output) { | 374 | if (oxfw->has_output) { |
366 | amdtp_stream_stop(&oxfw->tx_stream); | 375 | amdtp_stream_stop(&oxfw->tx_stream); |
367 | cmp_connection_break(&oxfw->out_conn); | 376 | cmp_connection_break(&oxfw->out_conn); |
377 | cmp_connection_release(&oxfw->out_conn); | ||
368 | } | 378 | } |
369 | } | 379 | } |
370 | } | 380 | } |