aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2012-03-18 14:05:29 -0400
committerStefan Richter <stefanr@s5r6.in-berlin.de>2012-03-18 17:15:39 -0400
commit18d627113b830cda80792e96b28341bcd41cf40c (patch)
tree44281ec110668e9f7a583303b28ba2ca47012a20 /drivers/firewire
parent910e76c607546ead218de8b11c32597d6b8fe7e4 (diff)
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 <clemens@ladisch.de> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire')
-rw-r--r--drivers/firewire/core-cdev.c2
-rw-r--r--drivers/firewire/ohci.c18
2 files changed, 10 insertions, 10 deletions
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c
index f5f5a9706fcc..4cb27dc542ce 100644
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -51,7 +51,7 @@
51/* 51/*
52 * ABI version history is documented in linux/firewire-cdev.h. 52 * ABI version history is documented in linux/firewire-cdev.h.
53 */ 53 */
54#define FW_CDEV_KERNEL_VERSION 4 54#define FW_CDEV_KERNEL_VERSION 5
55#define FW_CDEV_VERSION_EVENT_REQUEST2 4 55#define FW_CDEV_VERSION_EVENT_REQUEST2 4
56#define FW_CDEV_VERSION_ALLOCATE_REGION_END 4 56#define FW_CDEV_VERSION_ALLOCATE_REGION_END 4
57 57
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 07d3c8d58b30..632562667a01 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)
2689 u32 *ctx_hdr; 2689 u32 *ctx_hdr;
2690 2690
2691 if (ctx->header_length + ctx->base.header_size > PAGE_SIZE) 2691 if (ctx->header_length + ctx->base.header_size > PAGE_SIZE)
2692 return; 2692 flush_iso_completions(ctx);
2693 2693
2694 ctx_hdr = ctx->header + ctx->header_length; 2694 ctx_hdr = ctx->header + ctx->header_length;
2695 ctx->last_timestamp = (u16)le32_to_cpu((__force __le32)dma_hdr[0]); 2695 ctx->last_timestamp = (u16)le32_to_cpu((__force __le32)dma_hdr[0]);
@@ -2826,16 +2826,16 @@ static int handle_it_packet(struct context *context,
2826 2826
2827 sync_it_packet_for_cpu(context, d); 2827 sync_it_packet_for_cpu(context, d);
2828 2828
2829 if (ctx->header_length + 4 < PAGE_SIZE) { 2829 if (ctx->header_length + 4 > PAGE_SIZE)
2830 ctx_hdr = ctx->header + ctx->header_length; 2830 flush_iso_completions(ctx);
2831 /* Present this value as big-endian to match the receive code */
2832 *ctx_hdr = cpu_to_be32(
2833 ((u32)le16_to_cpu(pd->transfer_status) << 16) |
2834 le16_to_cpu(pd->res_count));
2835 ctx->header_length += 4;
2836 }
2837 2831
2832 ctx_hdr = ctx->header + ctx->header_length;
2838 ctx->last_timestamp = le16_to_cpu(last->res_count); 2833 ctx->last_timestamp = le16_to_cpu(last->res_count);
2834 /* Present this value as big-endian to match the receive code */
2835 *ctx_hdr = cpu_to_be32((le16_to_cpu(pd->transfer_status) << 16) |
2836 le16_to_cpu(pd->res_count));
2837 ctx->header_length += 4;
2838
2839 if (last->control & cpu_to_le16(DESCRIPTOR_IRQ_ALWAYS)) 2839 if (last->control & cpu_to_le16(DESCRIPTOR_IRQ_ALWAYS))
2840 flush_iso_completions(ctx); 2840 flush_iso_completions(ctx);
2841 2841