diff options
author | Clemens Ladisch <clemens@ladisch.de> | 2010-04-12 04:35:44 -0400 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2010-04-19 13:58:32 -0400 |
commit | e1393667be574807a13bfaf1bb471f5fd1a5287b (patch) | |
tree | 5f2084f1a5099062cb27e74765ec3cd8a69c3489 /drivers/firewire | |
parent | 2608203daf5f87311c6e5d36e5de5efcb14aab24 (diff) |
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>
Diffstat (limited to 'drivers/firewire')
-rw-r--r-- | drivers/firewire/ohci.c | 20 |
1 files changed, 13 insertions, 7 deletions
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 82fb2e7e99ef..6e95f8fb56db 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c | |||
@@ -1158,7 +1158,7 @@ static void handle_local_lock(struct fw_ohci *ohci, | |||
1158 | struct fw_packet *packet, u32 csr) | 1158 | struct fw_packet *packet, u32 csr) |
1159 | { | 1159 | { |
1160 | struct fw_packet response; | 1160 | struct fw_packet response; |
1161 | int tcode, length, ext_tcode, sel; | 1161 | int tcode, length, ext_tcode, sel, try; |
1162 | __be32 *payload, lock_old; | 1162 | __be32 *payload, lock_old; |
1163 | u32 lock_arg, lock_data; | 1163 | u32 lock_arg, lock_data; |
1164 | 1164 | ||
@@ -1185,13 +1185,19 @@ static void handle_local_lock(struct fw_ohci *ohci, | |||
1185 | reg_write(ohci, OHCI1394_CSRCompareData, lock_arg); | 1185 | reg_write(ohci, OHCI1394_CSRCompareData, lock_arg); |
1186 | reg_write(ohci, OHCI1394_CSRControl, sel); | 1186 | reg_write(ohci, OHCI1394_CSRControl, sel); |
1187 | 1187 | ||
1188 | if (reg_read(ohci, OHCI1394_CSRControl) & 0x80000000) | 1188 | for (try = 0; try < 20; try++) |
1189 | lock_old = cpu_to_be32(reg_read(ohci, OHCI1394_CSRData)); | 1189 | if (reg_read(ohci, OHCI1394_CSRControl) & 0x80000000) { |
1190 | else | 1190 | lock_old = cpu_to_be32(reg_read(ohci, |
1191 | fw_notify("swap not done yet\n"); | 1191 | OHCI1394_CSRData)); |
1192 | fw_fill_response(&response, packet->header, | ||
1193 | RCODE_COMPLETE, | ||
1194 | &lock_old, sizeof(lock_old)); | ||
1195 | goto out; | ||
1196 | } | ||
1197 | |||
1198 | fw_error("swap not done (CSR lock timeout)\n"); | ||
1199 | fw_fill_response(&response, packet->header, RCODE_BUSY, NULL, 0); | ||
1192 | 1200 | ||
1193 | fw_fill_response(&response, packet->header, | ||
1194 | RCODE_COMPLETE, &lock_old, sizeof(lock_old)); | ||
1195 | out: | 1201 | out: |
1196 | fw_core_handle_response(&ohci->card, &response); | 1202 | fw_core_handle_response(&ohci->card, &response); |
1197 | } | 1203 | } |