diff options
Diffstat (limited to 'sound/firewire/cmp.c')
-rw-r--r-- | sound/firewire/cmp.c | 50 |
1 files changed, 29 insertions, 21 deletions
diff --git a/sound/firewire/cmp.c b/sound/firewire/cmp.c index efdbf58..645cb0b 100644 --- a/sound/firewire/cmp.c +++ b/sound/firewire/cmp.c @@ -48,6 +48,9 @@ static int pcr_modify(struct cmp_connection *c, int (*check)(struct cmp_connection *c, __be32 pcr), enum bus_reset_handling bus_reset_handling) { + struct fw_device *device = fw_parent_device(c->resources.unit); + int generation = c->resources.generation; + int rcode, errors = 0; __be32 old_arg, buffer[2]; int err; @@ -56,31 +59,36 @@ static int pcr_modify(struct cmp_connection *c, old_arg = buffer[0]; buffer[1] = modify(c, buffer[0]); - err = snd_fw_transaction( - c->resources.unit, TCODE_LOCK_COMPARE_SWAP, + rcode = fw_run_transaction( + device->card, TCODE_LOCK_COMPARE_SWAP, + device->node_id, generation, device->max_speed, CSR_REGISTER_BASE + CSR_IPCR(c->pcr_index), - buffer, 8, - FW_FIXED_GENERATION | c->resources.generation); - - if (err < 0) { - if (err == -EAGAIN && - bus_reset_handling == SUCCEED_ON_BUS_RESET) - err = 0; - return err; - } - - if (buffer[0] == old_arg) /* success? */ - break; - - if (check) { - err = check(c, buffer[0]); - if (err < 0) - return err; - } + buffer, 8); + + if (rcode == RCODE_COMPLETE) { + if (buffer[0] == old_arg) /* success? */ + break; + + if (check) { + err = check(c, buffer[0]); + if (err < 0) + return err; + } + } else if (rcode == RCODE_GENERATION) + goto bus_reset; + else if (rcode_is_permanent_error(rcode) || ++errors >= 3) + goto io_error; } c->last_pcr_value = buffer[1]; return 0; + +io_error: + cmp_error(c, "transaction failed: %s\n", fw_rcode_string(rcode)); + return -EIO; + +bus_reset: + return bus_reset_handling == ABORT_ON_BUS_RESET ? -EAGAIN : 0; } @@ -100,7 +108,7 @@ int cmp_connection_init(struct cmp_connection *c, err = snd_fw_transaction(unit, TCODE_READ_QUADLET_REQUEST, CSR_REGISTER_BASE + CSR_IMPR, - &impr_be, 4, 0); + &impr_be, 4); if (err < 0) return err; impr = be32_to_cpu(impr_be); |