aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2013-07-22 15:32:09 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-08-04 04:50:38 -0400
commitf8c974f6fbdef40d37f957292f3238552a8d3598 (patch)
tree60392c81dcd63784f90d5e50952cce49a2963b94
parent6d2c6593cf6592707c68e95f43982adbe573c6ac (diff)
firewire: fix libdc1394/FlyCap2 iso event regression
commit 0699a73af3811b66b1ab5650575acee5eea841ab upstream. Commit 18d627113b83 (firewire: prevent dropping of completed iso packet header data) was intended to be an obvious bug fix, but libdc1394 and FlyCap2 depend on the old behaviour by ignoring all returned information and thus not noticing that not all packets have been received yet. The result was that the video frame buffers would be saved before they contained the correct data. Reintroduce the old behaviour for old clients. Tested-by: Stepan Salenikovich <stepan.salenikovich@gmail.com> Tested-by: Josep Bosch <jep250@gmail.com> 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/core-cdev.c3
-rw-r--r--drivers/firewire/ohci.c10
-rw-r--r--include/linux/firewire.h1
-rw-r--r--include/uapi/linux/firewire-cdev.h4
4 files changed, 14 insertions, 4 deletions
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c
index 7ef316fdc4d9..ac1b43a04285 100644
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -54,6 +54,7 @@
54#define FW_CDEV_KERNEL_VERSION 5 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#define FW_CDEV_VERSION_AUTO_FLUSH_ISO_OVERFLOW 5
57 58
58struct client { 59struct client {
59 u32 version; 60 u32 version;
@@ -1005,6 +1006,8 @@ static int ioctl_create_iso_context(struct client *client, union ioctl_arg *arg)
1005 a->channel, a->speed, a->header_size, cb, client); 1006 a->channel, a->speed, a->header_size, cb, client);
1006 if (IS_ERR(context)) 1007 if (IS_ERR(context))
1007 return PTR_ERR(context); 1008 return PTR_ERR(context);
1009 if (client->version < FW_CDEV_VERSION_AUTO_FLUSH_ISO_OVERFLOW)
1010 context->drop_overflow_headers = true;
1008 1011
1009 /* We only support one context at this time. */ 1012 /* We only support one context at this time. */
1010 spin_lock_irq(&client->lock); 1013 spin_lock_irq(&client->lock);
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 9e1db6490b9a..afb701ec90ca 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -2749,8 +2749,11 @@ static void copy_iso_headers(struct iso_context *ctx, const u32 *dma_hdr)
2749{ 2749{
2750 u32 *ctx_hdr; 2750 u32 *ctx_hdr;
2751 2751
2752 if (ctx->header_length + ctx->base.header_size > PAGE_SIZE) 2752 if (ctx->header_length + ctx->base.header_size > PAGE_SIZE) {
2753 if (ctx->base.drop_overflow_headers)
2754 return;
2753 flush_iso_completions(ctx); 2755 flush_iso_completions(ctx);
2756 }
2754 2757
2755 ctx_hdr = ctx->header + ctx->header_length; 2758 ctx_hdr = ctx->header + ctx->header_length;
2756 ctx->last_timestamp = (u16)le32_to_cpu((__force __le32)dma_hdr[0]); 2759 ctx->last_timestamp = (u16)le32_to_cpu((__force __le32)dma_hdr[0]);
@@ -2910,8 +2913,11 @@ static int handle_it_packet(struct context *context,
2910 2913
2911 sync_it_packet_for_cpu(context, d); 2914 sync_it_packet_for_cpu(context, d);
2912 2915
2913 if (ctx->header_length + 4 > PAGE_SIZE) 2916 if (ctx->header_length + 4 > PAGE_SIZE) {
2917 if (ctx->base.drop_overflow_headers)
2918 return 1;
2914 flush_iso_completions(ctx); 2919 flush_iso_completions(ctx);
2920 }
2915 2921
2916 ctx_hdr = ctx->header + ctx->header_length; 2922 ctx_hdr = ctx->header + ctx->header_length;
2917 ctx->last_timestamp = le16_to_cpu(last->res_count); 2923 ctx->last_timestamp = le16_to_cpu(last->res_count);
diff --git a/include/linux/firewire.h b/include/linux/firewire.h
index 191501afd7fb..217e4b42b7c8 100644
--- a/include/linux/firewire.h
+++ b/include/linux/firewire.h
@@ -434,6 +434,7 @@ struct fw_iso_context {
434 int type; 434 int type;
435 int channel; 435 int channel;
436 int speed; 436 int speed;
437 bool drop_overflow_headers;
437 size_t header_size; 438 size_t header_size;
438 union { 439 union {
439 fw_iso_callback_t sc; 440 fw_iso_callback_t sc;
diff --git a/include/uapi/linux/firewire-cdev.h b/include/uapi/linux/firewire-cdev.h
index d50036953497..1db453e4b550 100644
--- a/include/uapi/linux/firewire-cdev.h
+++ b/include/uapi/linux/firewire-cdev.h
@@ -215,8 +215,8 @@ struct fw_cdev_event_request2 {
215 * with the %FW_CDEV_ISO_INTERRUPT bit set, when explicitly requested with 215 * with the %FW_CDEV_ISO_INTERRUPT bit set, when explicitly requested with
216 * %FW_CDEV_IOC_FLUSH_ISO, or when there have been so many completed packets 216 * %FW_CDEV_IOC_FLUSH_ISO, or when there have been so many completed packets
217 * without the interrupt bit set that the kernel's internal buffer for @header 217 * without the interrupt bit set that the kernel's internal buffer for @header
218 * is about to overflow. (In the last case, kernels with ABI version < 5 drop 218 * is about to overflow. (In the last case, ABI versions < 5 drop header data
219 * header data up to the next interrupt packet.) 219 * up to the next interrupt packet.)
220 * 220 *
221 * Isochronous transmit events (context type %FW_CDEV_ISO_CONTEXT_TRANSMIT): 221 * Isochronous transmit events (context type %FW_CDEV_ISO_CONTEXT_TRANSMIT):
222 * 222 *