aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2012-03-12 21:45:47 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-04-02 09:27:13 -0700
commit07ef0938d89b3c5af9d3ff23e482b26202bd012c (patch)
tree7ec972b4c806a1936030a7a94f42387581fe2248
parentdfa5919bcc4079b0d48bb0441da8d5b144fef34f (diff)
firewire: ohci: fix too-early completion of IR multichannel buffers
commit 0c0efbacab8d70700d13301e0ae7975783c0cb0a upstream. 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> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-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 7f97c309790..271fc518dec 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -2558,15 +2558,14 @@ static int handle_ir_buffer_fill(struct context *context,
struct iso_context *ctx =
container_of(context, struct iso_context, context);
- if (!last->transfer_status)
+ if (last->res_count != 0)
/* Descriptor(s) not done yet, stop iteration */
return 0;
if (le16_to_cpu(last->control) & DESCRIPTOR_IRQ_ALWAYS)
ctx->base.callback.mc(&ctx->base,
le32_to_cpu(last->data_address) +
- le16_to_cpu(last->req_count) -
- le16_to_cpu(last->res_count),
+ le16_to_cpu(last->req_count),
ctx->base.callback_data);
return 1;