aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/firewire/core-card.c6
-rw-r--r--drivers/firewire/core-cdev.c12
-rw-r--r--drivers/firewire/core-iso.c6
-rw-r--r--drivers/firewire/core.h2
-rw-r--r--drivers/firewire/ohci.c78
-rw-r--r--include/linux/firewire-cdev.h35
-rw-r--r--include/linux/firewire.h1
7 files changed, 127 insertions, 13 deletions
diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c
index b19db0f6a254..cc595eba7ba9 100644
--- a/drivers/firewire/core-card.c
+++ b/drivers/firewire/core-card.c
@@ -650,6 +650,11 @@ static void dummy_flush_queue_iso(struct fw_iso_context *ctx)
650{ 650{
651} 651}
652 652
653static int dummy_flush_iso_completions(struct fw_iso_context *ctx)
654{
655 return -ENODEV;
656}
657
653static const struct fw_card_driver dummy_driver_template = { 658static const struct fw_card_driver dummy_driver_template = {
654 .read_phy_reg = dummy_read_phy_reg, 659 .read_phy_reg = dummy_read_phy_reg,
655 .update_phy_reg = dummy_update_phy_reg, 660 .update_phy_reg = dummy_update_phy_reg,
@@ -662,6 +667,7 @@ static const struct fw_card_driver dummy_driver_template = {
662 .set_iso_channels = dummy_set_iso_channels, 667 .set_iso_channels = dummy_set_iso_channels,
663 .queue_iso = dummy_queue_iso, 668 .queue_iso = dummy_queue_iso,
664 .flush_queue_iso = dummy_flush_queue_iso, 669 .flush_queue_iso = dummy_flush_queue_iso,
670 .flush_iso_completions = dummy_flush_iso_completions,
665}; 671};
666 672
667void fw_card_release(struct kref *kref) 673void fw_card_release(struct kref *kref)
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c
index 4cb27dc542ce..22c6df5f136d 100644
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -438,6 +438,7 @@ union ioctl_arg {
438 struct fw_cdev_send_phy_packet send_phy_packet; 438 struct fw_cdev_send_phy_packet send_phy_packet;
439 struct fw_cdev_receive_phy_packets receive_phy_packets; 439 struct fw_cdev_receive_phy_packets receive_phy_packets;
440 struct fw_cdev_set_iso_channels set_iso_channels; 440 struct fw_cdev_set_iso_channels set_iso_channels;
441 struct fw_cdev_flush_iso flush_iso;
441}; 442};
442 443
443static int ioctl_get_info(struct client *client, union ioctl_arg *arg) 444static int ioctl_get_info(struct client *client, union ioctl_arg *arg)
@@ -1168,6 +1169,16 @@ static int ioctl_stop_iso(struct client *client, union ioctl_arg *arg)
1168 return fw_iso_context_stop(client->iso_context); 1169 return fw_iso_context_stop(client->iso_context);
1169} 1170}
1170 1171
1172static int ioctl_flush_iso(struct client *client, union ioctl_arg *arg)
1173{
1174 struct fw_cdev_flush_iso *a = &arg->flush_iso;
1175
1176 if (client->iso_context == NULL || a->handle != 0)
1177 return -EINVAL;
1178
1179 return fw_iso_context_flush_completions(client->iso_context);
1180}
1181
1171static int ioctl_get_cycle_timer2(struct client *client, union ioctl_arg *arg) 1182static int ioctl_get_cycle_timer2(struct client *client, union ioctl_arg *arg)
1172{ 1183{
1173 struct fw_cdev_get_cycle_timer2 *a = &arg->get_cycle_timer2; 1184 struct fw_cdev_get_cycle_timer2 *a = &arg->get_cycle_timer2;
@@ -1589,6 +1600,7 @@ static int (* const ioctl_handlers[])(struct client *, union ioctl_arg *) = {
1589 [0x15] = ioctl_send_phy_packet, 1600 [0x15] = ioctl_send_phy_packet,
1590 [0x16] = ioctl_receive_phy_packets, 1601 [0x16] = ioctl_receive_phy_packets,
1591 [0x17] = ioctl_set_iso_channels, 1602 [0x17] = ioctl_set_iso_channels,
1603 [0x18] = ioctl_flush_iso,
1592}; 1604};
1593 1605
1594static int dispatch_ioctl(struct client *client, 1606static int dispatch_ioctl(struct client *client,
diff --git a/drivers/firewire/core-iso.c b/drivers/firewire/core-iso.c
index 57c3973093ad..2f432a20ce7e 100644
--- a/drivers/firewire/core-iso.c
+++ b/drivers/firewire/core-iso.c
@@ -191,6 +191,12 @@ void fw_iso_context_queue_flush(struct fw_iso_context *ctx)
191} 191}
192EXPORT_SYMBOL(fw_iso_context_queue_flush); 192EXPORT_SYMBOL(fw_iso_context_queue_flush);
193 193
194int fw_iso_context_flush_completions(struct fw_iso_context *ctx)
195{
196 return ctx->card->driver->flush_iso_completions(ctx);
197}
198EXPORT_SYMBOL(fw_iso_context_flush_completions);
199
194int fw_iso_context_stop(struct fw_iso_context *ctx) 200int fw_iso_context_stop(struct fw_iso_context *ctx)
195{ 201{
196 return ctx->card->driver->stop_iso(ctx); 202 return ctx->card->driver->stop_iso(ctx);
diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h
index 62f57a4331e3..9047f5547d98 100644
--- a/drivers/firewire/core.h
+++ b/drivers/firewire/core.h
@@ -106,6 +106,8 @@ struct fw_card_driver {
106 106
107 void (*flush_queue_iso)(struct fw_iso_context *ctx); 107 void (*flush_queue_iso)(struct fw_iso_context *ctx);
108 108
109 int (*flush_iso_completions)(struct fw_iso_context *ctx);
110
109 int (*stop_iso)(struct fw_iso_context *ctx); 111 int (*stop_iso)(struct fw_iso_context *ctx);
110}; 112};
111 113
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
index 632562667a01..59e7894ae3b8 100644
--- a/drivers/firewire/ohci.c
+++ b/drivers/firewire/ohci.c
@@ -172,6 +172,9 @@ struct iso_context {
172 struct context context; 172 struct context context;
173 void *header; 173 void *header;
174 size_t header_length; 174 size_t header_length;
175 unsigned long flushing_completions;
176 u32 mc_buffer_bus;
177 u16 mc_completed;
175 u16 last_timestamp; 178 u16 last_timestamp;
176 u8 sync; 179 u8 sync;
177 u8 tags; 180 u8 tags;
@@ -2749,28 +2752,51 @@ static int handle_ir_buffer_fill(struct context *context,
2749{ 2752{
2750 struct iso_context *ctx = 2753 struct iso_context *ctx =
2751 container_of(context, struct iso_context, context); 2754 container_of(context, struct iso_context, context);
2755 unsigned int req_count, res_count, completed;
2752 u32 buffer_dma; 2756 u32 buffer_dma;
2753 2757
2754 if (last->res_count != 0) 2758 req_count = le16_to_cpu(last->req_count);
2759 res_count = le16_to_cpu(ACCESS_ONCE(last->res_count));
2760 completed = req_count - res_count;
2761 buffer_dma = le32_to_cpu(last->data_address);
2762
2763 if (completed > 0) {
2764 ctx->mc_buffer_bus = buffer_dma;
2765 ctx->mc_completed = completed;
2766 }
2767
2768 if (res_count != 0)
2755 /* Descriptor(s) not done yet, stop iteration */ 2769 /* Descriptor(s) not done yet, stop iteration */
2756 return 0; 2770 return 0;
2757 2771
2758 buffer_dma = le32_to_cpu(last->data_address);
2759 dma_sync_single_range_for_cpu(context->ohci->card.device, 2772 dma_sync_single_range_for_cpu(context->ohci->card.device,
2760 buffer_dma & PAGE_MASK, 2773 buffer_dma & PAGE_MASK,
2761 buffer_dma & ~PAGE_MASK, 2774 buffer_dma & ~PAGE_MASK,
2762 le16_to_cpu(last->req_count), 2775 completed, DMA_FROM_DEVICE);
2763 DMA_FROM_DEVICE);
2764 2776
2765 if (last->control & cpu_to_le16(DESCRIPTOR_IRQ_ALWAYS)) 2777 if (last->control & cpu_to_le16(DESCRIPTOR_IRQ_ALWAYS)) {
2766 ctx->base.callback.mc(&ctx->base, 2778 ctx->base.callback.mc(&ctx->base,
2767 le32_to_cpu(last->data_address) + 2779 buffer_dma + completed,
2768 le16_to_cpu(last->req_count),
2769 ctx->base.callback_data); 2780 ctx->base.callback_data);
2781 ctx->mc_completed = 0;
2782 }
2770 2783
2771 return 1; 2784 return 1;
2772} 2785}
2773 2786
2787static void flush_ir_buffer_fill(struct iso_context *ctx)
2788{
2789 dma_sync_single_range_for_cpu(ctx->context.ohci->card.device,
2790 ctx->mc_buffer_bus & PAGE_MASK,
2791 ctx->mc_buffer_bus & ~PAGE_MASK,
2792 ctx->mc_completed, DMA_FROM_DEVICE);
2793
2794 ctx->base.callback.mc(&ctx->base,
2795 ctx->mc_buffer_bus + ctx->mc_completed,
2796 ctx->base.callback_data);
2797 ctx->mc_completed = 0;
2798}
2799
2774static inline void sync_it_packet_for_cpu(struct context *context, 2800static inline void sync_it_packet_for_cpu(struct context *context,
2775 struct descriptor *pd) 2801 struct descriptor *pd)
2776{ 2802{
@@ -2925,8 +2951,10 @@ static struct fw_iso_context *ohci_allocate_iso_context(struct fw_card *card,
2925 if (ret < 0) 2951 if (ret < 0)
2926 goto out_with_header; 2952 goto out_with_header;
2927 2953
2928 if (type == FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL) 2954 if (type == FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL) {
2929 set_multichannel_mask(ohci, 0); 2955 set_multichannel_mask(ohci, 0);
2956 ctx->mc_completed = 0;
2957 }
2930 2958
2931 return &ctx->base; 2959 return &ctx->base;
2932 2960
@@ -3388,6 +3416,39 @@ static void ohci_flush_queue_iso(struct fw_iso_context *base)
3388 reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE); 3416 reg_write(ctx->ohci, CONTROL_SET(ctx->regs), CONTEXT_WAKE);
3389} 3417}
3390 3418
3419static int ohci_flush_iso_completions(struct fw_iso_context *base)
3420{
3421 struct iso_context *ctx = container_of(base, struct iso_context, base);
3422 int ret = 0;
3423
3424 tasklet_disable(&ctx->context.tasklet);
3425
3426 if (!test_and_set_bit_lock(0, &ctx->flushing_completions)) {
3427 context_tasklet((unsigned long)&ctx->context);
3428
3429 switch (base->type) {
3430 case FW_ISO_CONTEXT_TRANSMIT:
3431 case FW_ISO_CONTEXT_RECEIVE:
3432 if (ctx->header_length != 0)
3433 flush_iso_completions(ctx);
3434 break;
3435 case FW_ISO_CONTEXT_RECEIVE_MULTICHANNEL:
3436 if (ctx->mc_completed != 0)
3437 flush_ir_buffer_fill(ctx);
3438 break;
3439 default:
3440 ret = -ENOSYS;
3441 }
3442
3443 clear_bit_unlock(0, &ctx->flushing_completions);
3444 smp_mb__after_clear_bit();
3445 }
3446
3447 tasklet_enable(&ctx->context.tasklet);
3448
3449 return ret;
3450}
3451
3391static const struct fw_card_driver ohci_driver = { 3452static const struct fw_card_driver ohci_driver = {
3392 .enable = ohci_enable, 3453 .enable = ohci_enable,
3393 .read_phy_reg = ohci_read_phy_reg, 3454 .read_phy_reg = ohci_read_phy_reg,
@@ -3405,6 +3466,7 @@ static const struct fw_card_driver ohci_driver = {
3405 .set_iso_channels = ohci_set_iso_channels, 3466 .set_iso_channels = ohci_set_iso_channels,
3406 .queue_iso = ohci_queue_iso, 3467 .queue_iso = ohci_queue_iso,
3407 .flush_queue_iso = ohci_flush_queue_iso, 3468 .flush_queue_iso = ohci_flush_queue_iso,
3469 .flush_iso_completions = ohci_flush_iso_completions,
3408 .start_iso = ohci_start_iso, 3470 .start_iso = ohci_start_iso,
3409 .stop_iso = ohci_stop_iso, 3471 .stop_iso = ohci_stop_iso,
3410}; 3472};
diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h
index b9bd349c6930..d50036953497 100644
--- a/include/linux/firewire-cdev.h
+++ b/include/linux/firewire-cdev.h
@@ -212,10 +212,11 @@ struct fw_cdev_event_request2 {
212 * @header: Stripped headers, if any 212 * @header: Stripped headers, if any
213 * 213 *
214 * This event is sent when the controller has completed an &fw_cdev_iso_packet 214 * This event is sent when the controller has completed an &fw_cdev_iso_packet
215 * with the %FW_CDEV_ISO_INTERRUPT bit set, or when there have been so many 215 * with the %FW_CDEV_ISO_INTERRUPT bit set, when explicitly requested with
216 * completed packets without the interrupt bit set that the kernel's internal 216 * %FW_CDEV_IOC_FLUSH_ISO, or when there have been so many completed packets
217 * buffer for @header is about to overflow. (In the latter case, kernels with 217 * without the interrupt bit set that the kernel's internal buffer for @header
218 * ABI version < 5 drop header data up to the next interrupt packet.) 218 * is about to overflow. (In the last case, kernels with ABI version < 5 drop
219 * header data up to the next interrupt packet.)
219 * 220 *
220 * Isochronous transmit events (context type %FW_CDEV_ISO_CONTEXT_TRANSMIT): 221 * Isochronous transmit events (context type %FW_CDEV_ISO_CONTEXT_TRANSMIT):
221 * 222 *
@@ -271,7 +272,8 @@ struct fw_cdev_event_iso_interrupt {
271 * This event is sent in multichannel contexts (context type 272 * This event is sent in multichannel contexts (context type
272 * %FW_CDEV_ISO_CONTEXT_RECEIVE_MULTICHANNEL) for &fw_cdev_iso_packet buffer 273 * %FW_CDEV_ISO_CONTEXT_RECEIVE_MULTICHANNEL) for &fw_cdev_iso_packet buffer
273 * chunks that have been completely filled and that have the 274 * chunks that have been completely filled and that have the
274 * %FW_CDEV_ISO_INTERRUPT bit set. 275 * %FW_CDEV_ISO_INTERRUPT bit set, or when explicitly requested with
276 * %FW_CDEV_IOC_FLUSH_ISO.
275 * 277 *
276 * The buffer is continuously filled with the following data, per packet: 278 * The buffer is continuously filled with the following data, per packet:
277 * - the 1394 iso packet header as described at &fw_cdev_event_iso_interrupt, 279 * - the 1394 iso packet header as described at &fw_cdev_event_iso_interrupt,
@@ -421,6 +423,9 @@ union fw_cdev_event {
421#define FW_CDEV_IOC_RECEIVE_PHY_PACKETS _IOW('#', 0x16, struct fw_cdev_receive_phy_packets) 423#define FW_CDEV_IOC_RECEIVE_PHY_PACKETS _IOW('#', 0x16, struct fw_cdev_receive_phy_packets)
422#define FW_CDEV_IOC_SET_ISO_CHANNELS _IOW('#', 0x17, struct fw_cdev_set_iso_channels) 424#define FW_CDEV_IOC_SET_ISO_CHANNELS _IOW('#', 0x17, struct fw_cdev_set_iso_channels)
423 425
426/* available since kernel version 3.4 */
427#define FW_CDEV_IOC_FLUSH_ISO _IOW('#', 0x18, struct fw_cdev_flush_iso)
428
424/* 429/*
425 * ABI version history 430 * ABI version history
426 * 1 (2.6.22) - initial version 431 * 1 (2.6.22) - initial version
@@ -445,6 +450,7 @@ union fw_cdev_event {
445 * %FW_CDEV_IOC_SET_ISO_CHANNELS 450 * %FW_CDEV_IOC_SET_ISO_CHANNELS
446 * 5 (3.4) - send %FW_CDEV_EVENT_ISO_INTERRUPT events when needed to 451 * 5 (3.4) - send %FW_CDEV_EVENT_ISO_INTERRUPT events when needed to
447 * avoid dropping data 452 * avoid dropping data
453 * - added %FW_CDEV_IOC_FLUSH_ISO
448 */ 454 */
449 455
450/** 456/**
@@ -855,6 +861,25 @@ struct fw_cdev_stop_iso {
855}; 861};
856 862
857/** 863/**
864 * struct fw_cdev_flush_iso - flush completed iso packets
865 * @handle: handle of isochronous context to flush
866 *
867 * For %FW_CDEV_ISO_CONTEXT_TRANSMIT or %FW_CDEV_ISO_CONTEXT_RECEIVE contexts,
868 * report any completed packets.
869 *
870 * For %FW_CDEV_ISO_CONTEXT_RECEIVE_MULTICHANNEL contexts, report the current
871 * offset in the receive buffer, if it has changed; this is typically in the
872 * middle of some buffer chunk.
873 *
874 * Any %FW_CDEV_EVENT_ISO_INTERRUPT or %FW_CDEV_EVENT_ISO_INTERRUPT_MULTICHANNEL
875 * events generated by this ioctl are sent synchronously, i.e., are available
876 * for reading from the file descriptor when this ioctl returns.
877 */
878struct fw_cdev_flush_iso {
879 __u32 handle;
880};
881
882/**
858 * struct fw_cdev_get_cycle_timer - read cycle timer register 883 * struct fw_cdev_get_cycle_timer - read cycle timer register
859 * @local_time: system time, in microseconds since the Epoch 884 * @local_time: system time, in microseconds since the Epoch
860 * @cycle_timer: Cycle Time register contents 885 * @cycle_timer: Cycle Time register contents
diff --git a/include/linux/firewire.h b/include/linux/firewire.h
index ab5b7a18decf..cdc9b719e9c7 100644
--- a/include/linux/firewire.h
+++ b/include/linux/firewire.h
@@ -426,6 +426,7 @@ int fw_iso_context_queue(struct fw_iso_context *ctx,
426 struct fw_iso_buffer *buffer, 426 struct fw_iso_buffer *buffer,
427 unsigned long payload); 427 unsigned long payload);
428void fw_iso_context_queue_flush(struct fw_iso_context *ctx); 428void fw_iso_context_queue_flush(struct fw_iso_context *ctx);
429int fw_iso_context_flush_completions(struct fw_iso_context *ctx);
429int fw_iso_context_start(struct fw_iso_context *ctx, 430int fw_iso_context_start(struct fw_iso_context *ctx,
430 int cycle, int sync, int tags); 431 int cycle, int sync, int tags);
431int fw_iso_context_stop(struct fw_iso_context *ctx); 432int fw_iso_context_stop(struct fw_iso_context *ctx);