aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire/ohci.c
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2010-02-08 02:30:03 -0500
committerStefan Richter <stefanr@s5r6.in-berlin.de>2010-02-14 09:10:41 -0500
commit7f51a100bba517196ac4bdf29408d20ee1c771e8 (patch)
tree6e1af632f6a3f5ffd635a07c181125609297977a /drivers/firewire/ohci.c
parent110f82d7a2e0ff5a17617a9672f1ccb7e44bc0c6 (diff)
firewire: ohci: retransmit isochronous transmit packets on cycle loss
In isochronous transmit DMA descriptors, link the skip address pointer back to the descriptor itself. When a cycle is lost, the controller will send the packet in the next cycle, instead of terminating the entire DMA program. There are two reasons for this: * This behaviour is compatible with the old IEEE1394 stack. Old applications would not expect the DMA program to stop in this case. * Since the OHCI driver does not report any uncompleted packets, the context would stop silently; clients would not have any chance to detect and handle this error without a watchdog timer. Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Pieter Palmers notes: "The reason I added this retry behavior to the old stack is because some cards now and then fail to send a packet (e.g. the o2micro card in my dell laptop). I couldn't figure out why exactly this happens, my best guess is that the card cannot fetch the payload data on time. This happens much more frequently when sending large packets, which leads me to suspect that there are some contention issues with the DMA that fills the transmit FIFO. In the old stack it was a pretty critical issue as it resulted in a freeze of the userspace application. The omission of a packet doesn't necessarily have to be an issue. E.g. in IEC61883 streams the DBC field can be used to detect discontinuities in the stream. So as long as the other side doesn't bail when no [packet] is present in a cycle, there is not really a problem. I'm not convinced though that retrying is the proper solution, but it is simple and effective for what it had to do. And I think there are no reasons not to do it this way. Userspace can still detect this by checking the cycle the descriptor was sent in." Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> (changelog, comment)
Diffstat (limited to 'drivers/firewire/ohci.c')
-rw-r--r--drivers/firewire/ohci.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 2345d4103fe6..43ebf337b131 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -2101,11 +2101,6 @@ static int ohci_queue_iso_transmit(struct fw_iso_context *base,
2101 u32 payload_index, payload_end_index, next_page_index; 2101 u32 payload_index, payload_end_index, next_page_index;
2102 int page, end_page, i, length, offset; 2102 int page, end_page, i, length, offset;
2103 2103
2104 /*
2105 * FIXME: Cycle lost behavior should be configurable: lose
2106 * packet, retransmit or terminate..
2107 */
2108
2109 p = packet; 2104 p = packet;
2110 payload_index = payload; 2105 payload_index = payload;
2111 2106
@@ -2135,6 +2130,14 @@ static int ohci_queue_iso_transmit(struct fw_iso_context *base,
2135 if (!p->skip) { 2130 if (!p->skip) {
2136 d[0].control = cpu_to_le16(DESCRIPTOR_KEY_IMMEDIATE); 2131 d[0].control = cpu_to_le16(DESCRIPTOR_KEY_IMMEDIATE);
2137 d[0].req_count = cpu_to_le16(8); 2132 d[0].req_count = cpu_to_le16(8);
2133 /*
2134 * Link the skip address to this descriptor itself. This causes
2135 * a context to skip a cycle whenever lost cycles or FIFO
2136 * overruns occur, without dropping the data. The application
2137 * should then decide whether this is an error condition or not.
2138 * FIXME: Make the context's cycle-lost behaviour configurable?
2139 */
2140 d[0].branch_address = cpu_to_le32(d_bus | z);
2138 2141
2139 header = (__le32 *) &d[1]; 2142 header = (__le32 *) &d[1];
2140 header[0] = cpu_to_le32(IT_HEADER_SY(p->sy) | 2143 header[0] = cpu_to_le32(IT_HEADER_SY(p->sy) |