@@ -89,13 +89,32 @@ static int pcr_modify(struct cmp_connection *c,
err = snd_fw_transaction(
c->resources.unit, TCODE_LOCK_COMPARE_SWAP,
get_offset(c, false), buffer, 8,
- FW_FIXED_GENERATION | c->resources.generation);
+ FW_FIXED_GENERATION | c->resources.generation |
+ FW_RETURN_TIMEOUT);
if (err < 0) {
if (err == -EAGAIN &&
bus_reset_handling == SUCCEED_ON_BUS_RESET)
err = 0;
- return err;
+
+ if (err != -ETIMEDOUT)
+ return err;
+
+ /* Check current PCR. */
+ err = snd_fw_transaction(
+ c->resources.unit, TCODE_READ_QUADLET_REQUEST,
+ get_offset(c, false), buffer, 4,
+ FW_FIXED_GENERATION | c->resources.generation);
+ if (err < 0)
+ return err;
+
+ /* The lock transaction may be failed, retry */
+ if (buffer[0] != buffer[1]) {
+ buffer[0] = c->last_pcr_value;
+ continue;
+ }
+
+ break;
}
if (buffer[0] == old_arg) /* success? */
@@ -245,8 +245,9 @@ int fcp_avc_transaction(struct fw_unit *unit,
: TCODE_WRITE_BLOCK_REQUEST;
ret = snd_fw_transaction(t.unit, tcode,
CSR_REGISTER_BASE + CSR_FCP_COMMAND,
- (void *)command, command_size, 0);
- if (ret < 0)
+ (void *)command, command_size,
+ FW_RETURN_TIMEOUT);
+ if ((ret < 0) && (ret != -ETIMEDOUT))
break;
wait_event_timeout(t.wait, t.state != STATE_PENDING,
@@ -22,7 +22,7 @@
* @length: length of @buffer
* @flags: use %FW_FIXED_GENERATION and add the generation value to attempt the
* request only in that generation; use %FW_QUIET to suppress error
- * messages
+ * messages; use %FW_RETURN_TIMEOUT to avoid retry at RCODE_CANCELLED
*
* Submits an asynchronous request to the target device, and waits for the
* response. The node ID and the current generation are derived from @unit.
@@ -53,6 +53,10 @@ int snd_fw_transaction(struct fw_unit *unit, int tcode,
if (rcode == RCODE_GENERATION && (flags & FW_FIXED_GENERATION))
return -EAGAIN;
+ /* timeout */
+ if ((rcode == RCODE_CANCELLED) && (flags & FW_RETURN_TIMEOUT))
+ return -ETIMEDOUT;
+
if (rcode_is_permanent_error(rcode) || ++tries >= 3) {
if (!(flags & FW_QUIET))
dev_err(&unit->device,
@@ -9,6 +9,7 @@ struct fw_unit;
#define FW_GENERATION_MASK 0x00ff
#define FW_FIXED_GENERATION 0x0100
#define FW_QUIET 0x0200
+#define FW_RETURN_TIMEOUT 0x0400
int snd_fw_transaction(struct fw_unit *unit, int tcode,
u64 offset, void *buffer, size_t length,