diff options
-rw-r--r-- | drivers/firewire/core-cdev.c | 3 | ||||
-rw-r--r-- | drivers/firewire/ohci.c | 10 | ||||
-rw-r--r-- | include/linux/firewire.h | 1 | ||||
-rw-r--r-- | include/uapi/linux/firewire-cdev.h | 4 |
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 | ||
58 | struct client { | 59 | struct 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 3b0e820375ab..5d7782e42b8f 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h | |||
@@ -436,6 +436,7 @@ struct fw_iso_context { | |||
436 | int type; | 436 | int type; |
437 | int channel; | 437 | int channel; |
438 | int speed; | 438 | int speed; |
439 | bool drop_overflow_headers; | ||
439 | size_t header_size; | 440 | size_t header_size; |
440 | union { | 441 | union { |
441 | fw_iso_callback_t sc; | 442 | 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 | * |