aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire
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
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')
-rw-r--r--drivers/firewire/core-card.c5
-rw-r--r--drivers/firewire/core-cdev.c1
-rw-r--r--drivers/firewire/core-iso.c6
-rw-r--r--drivers/firewire/core.h2
-rw-r--r--drivers/firewire/net.c4
-rw-r--r--drivers/firewire/ohci.c19
6 files changed, 32 insertions, 5 deletions
diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c
index e119f1e6ba47..f05fc7bfceeb 100644
--- a/drivers/firewire/core-card.c
+++ b/drivers/firewire/core-card.c
@@ -630,6 +630,10 @@ static int dummy_queue_iso(struct fw_iso_context *ctx, struct fw_iso_packet *p,
630 return -ENODEV; 630 return -ENODEV;
631} 631}
632 632
633static void dummy_flush_queue_iso(struct fw_iso_context *ctx)
634{
635}
636
633static const struct fw_card_driver dummy_driver_template = { 637static const struct fw_card_driver dummy_driver_template = {
634 .read_phy_reg = dummy_read_phy_reg, 638 .read_phy_reg = dummy_read_phy_reg,
635 .update_phy_reg = dummy_update_phy_reg, 639 .update_phy_reg = dummy_update_phy_reg,
@@ -641,6 +645,7 @@ static const struct fw_card_driver dummy_driver_template = {
641 .start_iso = dummy_start_iso, 645 .start_iso = dummy_start_iso,
642 .set_iso_channels = dummy_set_iso_channels, 646 .set_iso_channels = dummy_set_iso_channels,
643 .queue_iso = dummy_queue_iso, 647 .queue_iso = dummy_queue_iso,
648 .flush_queue_iso = dummy_flush_queue_iso,
644}; 649};
645 650
646void fw_card_release(struct kref *kref) 651void fw_card_release(struct kref *kref)
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c
index 2a3f1c4d6906..64768c2194f1 100644
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -1107,6 +1107,7 @@ static int ioctl_queue_iso(struct client *client, union ioctl_arg *arg)
1107 payload += u.packet.payload_length; 1107 payload += u.packet.payload_length;
1108 count++; 1108 count++;
1109 } 1109 }
1110 fw_iso_context_queue_flush(ctx);
1110 1111
1111 a->size -= uptr_to_u64(p) - a->packets; 1112 a->size -= uptr_to_u64(p) - a->packets;
1112 a->packets = uptr_to_u64(p); 1113 a->packets = uptr_to_u64(p);
diff --git a/drivers/firewire/core-iso.c b/drivers/firewire/core-iso.c
index f872ede5af37..57c3973093ad 100644
--- a/drivers/firewire/core-iso.c
+++ b/drivers/firewire/core-iso.c
@@ -185,6 +185,12 @@ int fw_iso_context_queue(struct fw_iso_context *ctx,
185} 185}
186EXPORT_SYMBOL(fw_iso_context_queue); 186EXPORT_SYMBOL(fw_iso_context_queue);
187 187
188void fw_iso_context_queue_flush(struct fw_iso_context *ctx)
189{
190 ctx->card->driver->flush_queue_iso(ctx);
191}
192EXPORT_SYMBOL(fw_iso_context_queue_flush);
193
188int fw_iso_context_stop(struct fw_iso_context *ctx) 194int fw_iso_context_stop(struct fw_iso_context *ctx)
189{ 195{
190 return ctx->card->driver->stop_iso(ctx); 196 return ctx->card->driver->stop_iso(ctx);
diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h
index 25e729cde2f7..0fe4e4e6eda7 100644
--- a/drivers/firewire/core.h
+++ b/drivers/firewire/core.h
@@ -97,6 +97,8 @@ struct fw_card_driver {
97 struct fw_iso_buffer *buffer, 97 struct fw_iso_buffer *buffer,
98 unsigned long payload); 98 unsigned long payload);
99 99
100 void (*flush_queue_iso)(struct fw_iso_context *ctx);
101
100 int (*stop_iso)(struct fw_iso_context *ctx); 102 int (*stop_iso)(struct fw_iso_context *ctx);
101}; 103};
102 104
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index 3f04dd3681cf..b9762d07198d 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -881,7 +881,9 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context,
881 881
882 spin_unlock_irqrestore(&dev->lock, flags); 882 spin_unlock_irqrestore(&dev->lock, flags);
883 883
884 if (retval < 0) 884 if (retval >= 0)
885 fw_iso_context_queue_flush(dev->broadcast_rcv_context);
886 else
885 fw_error("requeue failed\n"); 887 fw_error("requeue failed\n");
886} 888}
887 889
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};