From 18d627113b830cda80792e96b28341bcd41cf40c Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Sun, 18 Mar 2012 19:05:29 +0100 Subject: firewire: prevent dropping of completed iso packet header data The buffer for the header data of completed iso packets has a fixed size, so it is possible to configure a stream with a big interval between interrupt packets or with big headers so that this buffer would overflow. Previously, ohci.c would drop any data that would not fit, but this could make unsuspecting applications believe that fewer than the actual number of packets have completed. Instead of dropping data, add calls to flush_iso_completion() so that there are as many events as needed to report all of the data. Signed-off-by: Clemens Ladisch Signed-off-by: Stefan Richter --- drivers/firewire/ohci.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/firewire/ohci.c') diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 07d3c8d..6325626 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -2689,7 +2689,7 @@ static void copy_iso_headers(struct iso_context *ctx, const u32 *dma_hdr) u32 *ctx_hdr; if (ctx->header_length + ctx->base.header_size > PAGE_SIZE) - return; + flush_iso_completions(ctx); ctx_hdr = ctx->header + ctx->header_length; ctx->last_timestamp = (u16)le32_to_cpu((__force __le32)dma_hdr[0]); @@ -2826,16 +2826,16 @@ static int handle_it_packet(struct context *context, sync_it_packet_for_cpu(context, d); - if (ctx->header_length + 4 < PAGE_SIZE) { - ctx_hdr = ctx->header + ctx->header_length; - /* Present this value as big-endian to match the receive code */ - *ctx_hdr = cpu_to_be32( - ((u32)le16_to_cpu(pd->transfer_status) << 16) | - le16_to_cpu(pd->res_count)); - ctx->header_length += 4; - } + if (ctx->header_length + 4 > PAGE_SIZE) + flush_iso_completions(ctx); + ctx_hdr = ctx->header + ctx->header_length; ctx->last_timestamp = le16_to_cpu(last->res_count); + /* Present this value as big-endian to match the receive code */ + *ctx_hdr = cpu_to_be32((le16_to_cpu(pd->transfer_status) << 16) | + le16_to_cpu(pd->res_count)); + ctx->header_length += 4; + if (last->control & cpu_to_le16(DESCRIPTOR_IRQ_ALWAYS)) flush_iso_completions(ctx); -- cgit v1.1