summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/firewire/core-cdev.c2
-rw-r--r--drivers/firewire/ohci.c18
-rw-r--r--include/linux/firewire-cdev.h9
3 files changed, 17 insertions, 12 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 @@
/*
* ABI version history is documented in linux/firewire-cdev.h.
*/
-#define FW_CDEV_KERNEL_VERSION 4
+#define FW_CDEV_KERNEL_VERSION 5
#define FW_CDEV_VERSION_EVENT_REQUEST2 4
#define FW_CDEV_VERSION_ALLOCATE_REGION_END 4
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)
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);
diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h
index cc1b570a2eb3..b9bd349c6930 100644
--- a/include/linux/firewire-cdev.h
+++ b/include/linux/firewire-cdev.h
@@ -207,12 +207,15 @@ struct fw_cdev_event_request2 {
* @closure: See &fw_cdev_event_common;
* set by %FW_CDEV_CREATE_ISO_CONTEXT ioctl
* @type: See &fw_cdev_event_common; always %FW_CDEV_EVENT_ISO_INTERRUPT
- * @cycle: Cycle counter of the interrupt packet
+ * @cycle: Cycle counter of the last completed packet
* @header_length: Total length of following headers, in bytes
* @header: Stripped headers, if any
*
* This event is sent when the controller has completed an &fw_cdev_iso_packet
- * with the %FW_CDEV_ISO_INTERRUPT bit set.
+ * with the %FW_CDEV_ISO_INTERRUPT bit set, 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 latter case, kernels with
+ * ABI version < 5 drop header data up to the next interrupt packet.)
*
* Isochronous transmit events (context type %FW_CDEV_ISO_CONTEXT_TRANSMIT):
*
@@ -440,6 +443,8 @@ union fw_cdev_event {
* - added %FW_CDEV_EVENT_ISO_INTERRUPT_MULTICHANNEL,
* %FW_CDEV_ISO_CONTEXT_RECEIVE_MULTICHANNEL, and
* %FW_CDEV_IOC_SET_ISO_CHANNELS
+ * 5 (3.4) - send %FW_CDEV_EVENT_ISO_INTERRUPT events when needed to
+ * avoid dropping data
*/
/**
OpenPOWER on IntegriCloud