summaryrefslogtreecommitdiffstats
path: root/drivers/firewire
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2011-06-12 14:30:57 +0200
committerStefan Richter <stefanr@s5r6.in-berlin.de>2011-07-09 17:12:07 +0200
commit9ef28ccd59a23d219c4660f55a11ac06ca91f632 (patch)
treec65839983c1680c1cbb95c5d84c13e7386d49ce2 /drivers/firewire
parentfirewire: ohci: remove superfluous posted write flushes (diff)
downloadlinux-9ef28ccd59a23d219c4660f55a11ac06ca91f632.tar.xz
linux-9ef28ccd59a23d219c4660f55a11ac06ca91f632.zip
firewire: ohci: reduce potential context_stop latency
Stopping an isochronous reception DMA context takes two loop iterations in context_stop on several controllers (JMicron, NEC, VIA). But there is no extra delay necessary between these two reg_read trials; the MMIO reads themselves are slow enough. Hence bring back the behavior from before commit dd6254e5c0efe01ad255188898cb3dadf98cb56d "firewire: ohci: remove superfluous posted write flushes" on these controllers by means of an "if (i)" condition. Isochronous context stop is performed in preemptible contexts (and only rarely), hence this change is of little impact. (Besides, Agere and TI controllers always, or almost always, have the context stopped already at the first ContextControl read.) More important is asynchronous transmit context stop, which is performed while local interrupts are disabled (on the two AT DMAs in bus_reset_tasklet, i.e. after a self-ID-complete event). In my experience with several controllers, tested with a usermode AT-request transmitter as well as with FTP transmission over firewire-net, the AT contexts were luckily already stopped at the first ContextControl read, i.e. never required another MMIO read let alone mdelay. A possible explanation for this is that the controllers which I tested perhaps stop AT DMA before they perform the self-ID reception DMA. But we cannot be sure about that and should keep the interrupts-disabled busy loop as short as possible. Hence, query the ContextControl register in 1000 udelay(10) intervals instead of 10 udelay(1000) intervals. I understand from an estimation by Clemens Ladisch that stopping a busy DMA context should take microseconds or at worst tens of microseconds, not milliseconds. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire')
-rw-r--r--drivers/firewire/ohci.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index e291edaa5eef..3b6f3429fb4a 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -1200,12 +1200,13 @@ static void context_stop(struct context *ctx)
reg_write(ctx->ohci, CONTROL_CLEAR(ctx->regs), CONTEXT_RUN);
ctx->running = false;
- for (i = 0; i < 10; i++) {
+ for (i = 0; i < 1000; i++) {
reg = reg_read(ctx->ohci, CONTROL_SET(ctx->regs));
if ((reg & CONTEXT_ACTIVE) == 0)
return;
- mdelay(1);
+ if (i)
+ udelay(10);
}
fw_error("Error: DMA context still active (0x%08x)\n", reg);
}