aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire/ohci.c
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2011-05-02 03:33:56 -0400
committerStefan Richter <stefanr@s5r6.in-berlin.de>2011-05-10 16:53:45 -0400
commit13882a82ee1646336c3996c93b4a560a55d2a419 (patch)
tree8a144d874a0ac46273a7e2f2dd344458d7eb4bfa /drivers/firewire/ohci.c
parentf30e6d3e419bfb5540fa82ba7eca01d578556e6b (diff)
firewire: optimize iso queueing by setting wake only after the last packet
When queueing iso packets, the run time is dominated by the two MMIO accesses that set the DMA context's wake bit. Because most drivers submit packets in batches, we can save much time by removing all but the last wakeup. The internal kernel API is changed to require a call to fw_iso_context_queue_flush() after a batch of queued packets. The user space API does not change, so one call to FW_CDEV_IOC_QUEUE_ISO must specify multiple packets to take advantage of this optimization. In my measurements, this patch reduces the time needed to queue fifty skip packets from userspace to one sixth on a 2.5 GHz CPU, or to one third at 800 MHz. Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire/ohci.c')
-rw-r--r--drivers/firewire/ohci.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index f9f55703375e..438e6c831170 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -1192,9 +1192,6 @@ static void context_append(struct context *ctx,
1192 wmb(); /* finish init of new descriptors before branch_address update */ 1192 wmb(); /* finish init of new descriptors before branch_address update */
1193 ctx->prev->branch_address = cpu_to_le32(d_bus | z); 1193 ctx->prev->branch_address = cpu_to_le32(d_bus | z);
1194 ctx->prev = find_branch_descriptor(d, z); 1194 ctx->prev = find_branch_descriptor(d, z);
1195
1196 reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE);
1197 flush_writes(ctx->ohci);
1198} 1195}
1199 1196
1200static void context_stop(struct context *ctx) 1197static void context_stop(struct context *ctx)
@@ -1348,8 +1345,12 @@ static int at_context_queue_packet(struct context *ctx,
1348 1345
1349 context_append(ctx, d, z, 4 - z); 1346 context_append(ctx, d, z, 4 - z);
1350 1347
1351 if (!ctx->running) 1348 if (ctx->running) {
1349 reg_write(ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE);
1350 flush_writes(ohci);
1351 } else {
1352 context_run(ctx, 0); 1352 context_run(ctx, 0);
1353 }
1353 1354
1354 return 0; 1355 return 0;
1355} 1356}
@@ -3121,6 +3122,15 @@ static int ohci_queue_iso(struct fw_iso_context *base,
3121 return ret; 3122 return ret;
3122} 3123}
3123 3124
3125static void ohci_flush_queue_iso(struct fw_iso_context *base)
3126{
3127 struct context *ctx =
3128 &container_of(base, struct iso_context, base)->context;
3129
3130 reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE);
3131 flush_writes(ctx->ohci);
3132}
3133
3124static const struct fw_card_driver ohci_driver = { 3134static const struct fw_card_driver ohci_driver = {
3125 .enable = ohci_enable, 3135 .enable = ohci_enable,
3126 .read_phy_reg = ohci_read_phy_reg, 3136 .read_phy_reg = ohci_read_phy_reg,
@@ -3137,6 +3147,7 @@ static const struct fw_card_driver ohci_driver = {
3137 .free_iso_context = ohci_free_iso_context, 3147 .free_iso_context = ohci_free_iso_context,
3138 .set_iso_channels = ohci_set_iso_channels, 3148 .set_iso_channels = ohci_set_iso_channels,
3139 .queue_iso = ohci_queue_iso, 3149 .queue_iso = ohci_queue_iso,
3150 .flush_queue_iso = ohci_flush_queue_iso,
3140 .start_iso = ohci_start_iso, 3151 .start_iso = ohci_start_iso,
3141 .stop_iso = ohci_stop_iso, 3152 .stop_iso = ohci_stop_iso,
3142}; 3153};