summaryrefslogtreecommitdiffstats
path: root/sound/firewire/cmp.c
diff options
context:
space:
mode:
authorTakashi Sakamoto <o-takashi@sakamocchi.jp>2019-06-15 05:11:01 -0400
committerTakashi Iwai <tiwai@suse.de>2019-06-17 02:18:36 -0400
commit7bc93821a70adc621df443c8b7a4745023c36e7c (patch)
tree0474e9b97389716fb9e1320d6ceeba6b61be03d2 /sound/firewire/cmp.c
parentc6b84ffbd5e78d6cf4aaafe5502e1bc99eb9657c (diff)
ALSA: firewire-lib: split allocation of isochronous resources from establishment of connection
In current implementation, establishment connection corresponds to allocation of isochronous resources. Although this is an ideal implementation of CMP described in IEC 61883-1, it's not enough efficient to recover PCM substream multiplexed in packet streaming. The packet streaming can always restart on the same allocated isochronous resources even if the previous packet streaming corrupted. This commit splits allocation of isochronous resources from establishment of connection so that CMP runs with allocated isochronous resources. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/firewire/cmp.c')
-rw-r--r--sound/firewire/cmp.c74
1 files changed, 43 insertions, 31 deletions
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}
186EXPORT_SYMBOL(cmp_connection_destroy); 186EXPORT_SYMBOL(cmp_connection_destroy);
187 187
188int 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);
205end:
206 mutex_unlock(&c->mutex);
207
208 return err;
209}
210EXPORT_SYMBOL(cmp_connection_reserve);
211
212void 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}
218EXPORT_SYMBOL(cmp_connection_release);
188 219
189static __be32 ipcr_set_modify(struct cmp_connection *c, __be32 ipcr) 220static __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 */
273int cmp_connection_establish(struct cmp_connection *c, 304int 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
286retry_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
315retry_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
312err_resources:
313 fw_iso_resources_free(&c->resources);
314err_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
360err_resources:
361 fw_iso_resources_free(&c->resources);
362err_unconnect: 376err_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);