Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e1393667 authored by Clemens Ladisch's avatar Clemens Ladisch Committed by Stefan Richter
Browse files

firewire: ohci: wait for local CSR lock access to finish



Add a loop to wait for the controller to finish a locally-initiated CSR
lock operation.  Google shows some occurrences of the "swap not done
yet" message which might indicate that some OHCI controllers are not
fast enough to do the lock/swap in the time needed for one PCI access.

This also correctly handles the case where the lock operation did not
finish, instead of silently returning an uninitialized value.

Signed-off-by: default avatarClemens Ladisch <clemens@ladisch.de>
Signed-off-by: default avatarStefan Richter <stefanr@s5r6.in-berlin.de>
parent 2608203d
Loading
Loading
Loading
Loading
+13 −7
Original line number Diff line number Diff line
@@ -1158,7 +1158,7 @@ static void handle_local_lock(struct fw_ohci *ohci,
			      struct fw_packet *packet, u32 csr)
{
	struct fw_packet response;
	int tcode, length, ext_tcode, sel;
	int tcode, length, ext_tcode, sel, try;
	__be32 *payload, lock_old;
	u32 lock_arg, lock_data;

@@ -1185,13 +1185,19 @@ static void handle_local_lock(struct fw_ohci *ohci,
	reg_write(ohci, OHCI1394_CSRCompareData, lock_arg);
	reg_write(ohci, OHCI1394_CSRControl, sel);

	if (reg_read(ohci, OHCI1394_CSRControl) & 0x80000000)
		lock_old = cpu_to_be32(reg_read(ohci, OHCI1394_CSRData));
	else
		fw_notify("swap not done yet\n");

	for (try = 0; try < 20; try++)
		if (reg_read(ohci, OHCI1394_CSRControl) & 0x80000000) {
			lock_old = cpu_to_be32(reg_read(ohci,
							OHCI1394_CSRData));
			fw_fill_response(&response, packet->header,
			 RCODE_COMPLETE, &lock_old, sizeof(lock_old));
					 RCODE_COMPLETE,
					 &lock_old, sizeof(lock_old));
			goto out;
		}

	fw_error("swap not done (CSR lock timeout)\n");
	fw_fill_response(&response, packet->header, RCODE_BUSY, NULL, 0);

 out:
	fw_core_handle_response(&ohci->card, &response);
}