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: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
This commit is contained in:
parent
2608203daf
commit
e1393667be
1 changed files with 13 additions and 7 deletions
|
@ -1158,7 +1158,7 @@ static void handle_local_lock(struct fw_ohci *ohci,
|
||||||
struct fw_packet *packet, u32 csr)
|
struct fw_packet *packet, u32 csr)
|
||||||
{
|
{
|
||||||
struct fw_packet response;
|
struct fw_packet response;
|
||||||
int tcode, length, ext_tcode, sel;
|
int tcode, length, ext_tcode, sel, try;
|
||||||
__be32 *payload, lock_old;
|
__be32 *payload, lock_old;
|
||||||
u32 lock_arg, lock_data;
|
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_CSRCompareData, lock_arg);
|
||||||
reg_write(ohci, OHCI1394_CSRControl, sel);
|
reg_write(ohci, OHCI1394_CSRControl, sel);
|
||||||
|
|
||||||
if (reg_read(ohci, OHCI1394_CSRControl) & 0x80000000)
|
for (try = 0; try < 20; try++)
|
||||||
lock_old = cpu_to_be32(reg_read(ohci, OHCI1394_CSRData));
|
if (reg_read(ohci, OHCI1394_CSRControl) & 0x80000000) {
|
||||||
else
|
lock_old = cpu_to_be32(reg_read(ohci,
|
||||||
fw_notify("swap not done yet\n");
|
OHCI1394_CSRData));
|
||||||
|
fw_fill_response(&response, packet->header,
|
||||||
|
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);
|
||||||
|
|
||||||
fw_fill_response(&response, packet->header,
|
|
||||||
RCODE_COMPLETE, &lock_old, sizeof(lock_old));
|
|
||||||
out:
|
out:
|
||||||
fw_core_handle_response(&ohci->card, &response);
|
fw_core_handle_response(&ohci->card, &response);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue