aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2012-03-12 16:45:47 -0400
committerStefan Richter <stefanr@s5r6.in-berlin.de>2012-03-17 06:07:26 -0400
commit0c0efbacab8d70700d13301e0ae7975783c0cb0a (patch)
tree40d3dc3ccc449c8731239bb13505f0c2101ab000 /drivers/firewire
parentcfda62baa474b194802a555d3f7f2ccfa27e28bb (diff)
firewire: ohci: fix too-early completion of IR multichannel buffers
handle_ir_buffer_fill() assumed that a completed descriptor would be indicated by a non-zero transfer_status (as in most other descriptors). However, this field is written by the controller as soon as (the end of) the first packet has been written into the buffer. As a consequence, if we happen to run into such a descriptor when the interrupt handler is executed after such a packet has completed, the descriptor would be taken out of the list of active descriptors as soon as the buffer had been partially filled, so the event for the buffer being completely filled would never be sent. To fix this, handle descriptors only when they have been completely filled, i.e., when res_count == 0. (This also matches the condition that is reported by the controller with an interrupt.) Signed-off-by: Clemens Ladisch <clemens@ladisch.de> Cc: 2.6.36+ <stable@vger.kernel.org> 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, 2 insertions, 3 deletions
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 384b5b08126c..e52615a14382 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -2751,7 +2751,7 @@ static int handle_ir_buffer_fill(struct context *context,
2751 container_of(context, struct iso_context, context); 2751 container_of(context, struct iso_context, context);
2752 u32 buffer_dma; 2752 u32 buffer_dma;
2753 2753
2754 if (!last->transfer_status) 2754 if (last->res_count != 0)
2755 /* Descriptor(s) not done yet, stop iteration */ 2755 /* Descriptor(s) not done yet, stop iteration */
2756 return 0; 2756 return 0;
2757 2757
@@ -2765,8 +2765,7 @@ static int handle_ir_buffer_fill(struct context *context,
2765 if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS) 2765 if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS)
2766 ctx->base.callback.mc(&ctx->base, 2766 ctx->base.callback.mc(&ctx->base,
2767 le32_to_cpu(last->data_address) + 2767 le32_to_cpu(last->data_address) +
2768 le16_to_cpu(last->req_count) - 2768 le16_to_cpu(last->req_count),
2769 le16_to_cpu(last->res_count),
2770 ctx->base.callback_data); 2769 ctx->base.callback_data);
2771 2770
2772 return 1; 2771 return 1;