Date: Mon, 12 Apr 2010 10:35:44 +0200 From: Clemens Ladisch Subject: 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 Signed-off-by: Stefan Richter --- drivers/firewire/ohci.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) Index: b/drivers/firewire/ohci.c =================================================================== --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -1206,7 +1206,7 @@ static void handle_local_lock(struct fw_ 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; @@ -1233,13 +1233,19 @@ static void handle_local_lock(struct fw_ 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)); + 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: fw_core_handle_response(&ohci->card, &response); }