summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2013-07-22 21:32:09 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-08-04 16:26:02 +0800
commita90a3adeda28c4b701b11770817cf86d92db3228 (patch)
tree4443439c0d4ea52b0cb411b4069286afeea3f170
parent8924588cf02036c239cfec4302f8b44ca6e2c6bb (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> Cc: <stable@vger.kernel.org> # 3.4+ 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-cdev.h4
-rw-r--r--include/linux/firewire.h1
4 files changed, 14 insertions, 4 deletions
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c
index b8e4809cae0e..b558810b2da0 100644
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -53,6 +53,7 @@
#define FW_CDEV_KERNEL_VERSION 5
#define FW_CDEV_VERSION_EVENT_REQUEST2 4
#define FW_CDEV_VERSION_ALLOCATE_REGION_END 4
+#define FW_CDEV_VERSION_AUTO_FLUSH_ISO_OVERFLOW 5
struct client {
u32 version;
@@ -998,6 +999,8 @@ static int ioctl_create_iso_context(struct client *client, union ioctl_arg *arg)
a->channel, a->speed, a->header_size, cb, client);
if (IS_ERR(context))
return PTR_ERR(context);
+ if (client->version < FW_CDEV_VERSION_AUTO_FLUSH_ISO_OVERFLOW)
+ context->drop_overflow_headers = true;
/* We only support one context at this time. */
spin_lock_irq(&client->lock);
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 2b5460075a9f..c1de4c3a3fe7 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -2694,8 +2694,11 @@ 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)
+ if (ctx->header_length + ctx->base.header_size > PAGE_SIZE) {
+ if (ctx->base.drop_overflow_headers)
+ return;
flush_iso_completions(ctx);
+ }
ctx_hdr = ctx->header + ctx->header_length;
ctx->last_timestamp = (u16)le32_to_cpu((__force __le32)dma_hdr[0]);
@@ -2855,8 +2858,11 @@ static int handle_it_packet(struct context *context,
sync_it_packet_for_cpu(context, d);
- if (ctx->header_length + 4 > PAGE_SIZE)
+ if (ctx->header_length + 4 > PAGE_SIZE) {
+ if (ctx->base.drop_overflow_headers)
+ return 1;
flush_iso_completions(ctx);
+ }
ctx_hdr = ctx->header + ctx->header_length;
ctx->last_timestamp = le16_to_cpu(last->res_count);
diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h
index d50036953497..1db453e4b550 100644
--- a/include/linux/firewire-cdev.h
+++ b/include/linux/firewire-cdev.h
@@ -215,8 +215,8 @@ struct fw_cdev_event_request2 {
* with the %FW_CDEV_ISO_INTERRUPT bit set, when explicitly requested with
* %FW_CDEV_IOC_FLUSH_ISO, or when there have been so many completed packets
* without the interrupt bit set that the kernel's internal buffer for @header
- * is about to overflow. (In the last case, kernels with ABI version < 5 drop
- * header data up to the next interrupt packet.)
+ * is about to overflow. (In the last case, ABI versions < 5 drop header data
+ * up to the next interrupt packet.)
*
* Isochronous transmit events (context type %FW_CDEV_ISO_CONTEXT_TRANSMIT):
*
diff --git a/include/linux/firewire.h b/include/linux/firewire.h
index cdc9b719e9c7..4d259fc7722c 100644
--- a/include/linux/firewire.h
+++ b/include/linux/firewire.h
@@ -409,6 +409,7 @@ struct fw_iso_context {
int type;
int channel;
int speed;
+ bool drop_overflow_headers;
size_t header_size;
union {
fw_iso_callback_t sc;