summaryrefslogtreecommitdiff
path: root/sound/firewire/cmp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/firewire/cmp.c')
-rw-r--r--sound/firewire/cmp.c50
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);