Samuel,
could you test whether the following patch works?
This approach keeps the door open to use at least one of the 8 IR DMA
contexts of FW643 in the more featureful dual-buffer mode. If a second
(3rd, ...) stream is started, then only these subsequent streams will be
forced to packet-per-buffer mode.
---
drivers/firewire/fw-ohci.c | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
Index: linux-2.6.30.5/drivers/firewire/fw-ohci.c
===================================================================
--- linux-2.6.30.5.orig/drivers/firewire/fw-ohci.c
+++ linux-2.6.30.5/drivers/firewire/fw-ohci.c
@@ -29,6 +29,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/pci.h>
+#include <linux/pci_ids.h>
#include <linux/spinlock.h>
#include <asm/page.h>
@@ -181,6 +182,7 @@ struct fw_ohci {
u32 bus_seconds;
bool use_dualbuffer;
+ bool single_dualbuffer;
bool old_uninorth;
bool bus_reset_packet_quirk;
@@ -1921,11 +1923,18 @@ static struct fw_iso_context *ohci_alloc
}
spin_lock_irqsave(&ohci->lock, flags);
+
+ if (type == FW_ISO_CONTEXT_RECEIVE &&
+ ohci->single_dualbuffer &&
+ *channels != ~0ULL)
+ callback = handle_ir_packet_per_buffer;
+
index = *channels & 1ULL << channel ? ffs(*mask) - 1 : -1;
if (index >= 0) {
*channels &= ~(1ULL << channel);
*mask &= ~(1 << index);
}
+
spin_unlock_irqrestore(&ohci->lock, flags);
if (index < 0)
@@ -1980,7 +1989,7 @@ static int ohci_start_iso(struct fw_iso_
} else {
index = ctx - ohci->ir_context_list;
control = IR_CONTEXT_ISOCH_HEADER;
- if (ohci->use_dualbuffer)
+ if (ctx->context.callback == handle_ir_dualbuffer_packet)
control |= IR_CONTEXT_DUAL_BUFFER_MODE;
match = (tags << 28) | (sync << 8) | ctx->base.channel;
if (cycle >= 0) {
@@ -2308,7 +2317,7 @@ static int ohci_queue_iso(struct fw_iso_
spin_lock_irqsave(&ctx->context.ohci->lock, flags);
if (base->type == FW_ISO_CONTEXT_TRANSMIT)
ret = ohci_queue_iso_transmit(base, packet, buffer, payload);
- else if (ctx->context.ohci->use_dualbuffer)
+ else if (ctx->context.callback == handle_ir_dualbuffer_packet)
ret = ohci_queue_iso_receive_dualbuffer(base, packet,
buffer, payload);
else
@@ -2429,6 +2438,10 @@ static int __devinit pci_probe(struct pc
#endif
ohci->bus_reset_packet_quirk = dev->vendor == PCI_VENDOR_ID_TI;
+ /* dual-buffer mode is broken if more than one context is active */
+ ohci->single_dualbuffer = dev->vendor == PCI_VENDOR_ID_ATT &&
+ dev->device == 0x5901; /* FW643 */
+
ar_context_init(&ohci->ar_request_ctx, ohci,
OHCI1394_AsReqRcvContextControlSet);
--
Stefan Richter
-=====-==--= =--- =--==
http://arcgraph.de/sr/
|