diff options
author | Kristian Høgsberg <krh@redhat.com> | 2007-02-16 17:34:51 -0500 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2007-03-09 16:03:04 -0500 |
commit | 98b6cbe83b6e8db54638746c9040c7962d96b322 (patch) | |
tree | ad9d7587a5dde5510b402da8681e8c3d150d7ca5 /drivers/firewire | |
parent | 21efb3cfc6ed49991638000f58bb23b838c76e25 (diff) |
firewire: Implement sync and tag matching for isochronous receive.
Signed-off-by: Kristian Høgsberg <krh@redhat.com>
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire')
-rw-r--r-- | drivers/firewire/fw-device-cdev.c | 10 | ||||
-rw-r--r-- | drivers/firewire/fw-device-cdev.h | 8 | ||||
-rw-r--r-- | drivers/firewire/fw-iso.c | 8 | ||||
-rw-r--r-- | drivers/firewire/fw-ohci.c | 32 | ||||
-rw-r--r-- | drivers/firewire/fw-transaction.h | 13 |
5 files changed, 64 insertions, 7 deletions
diff --git a/drivers/firewire/fw-device-cdev.c b/drivers/firewire/fw-device-cdev.c index 5c876188677f..33fe5768a078 100644 --- a/drivers/firewire/fw-device-cdev.c +++ b/drivers/firewire/fw-device-cdev.c | |||
@@ -416,6 +416,12 @@ static int ioctl_create_iso_context(struct client *client, void __user *arg) | |||
416 | if (request.channel > 63) | 416 | if (request.channel > 63) |
417 | return -EINVAL; | 417 | return -EINVAL; |
418 | 418 | ||
419 | if (request.sync > 15) | ||
420 | return -EINVAL; | ||
421 | |||
422 | if (request.tags == 0 || request.tags > 15) | ||
423 | return -EINVAL; | ||
424 | |||
419 | if (request.speed > SCODE_3200) | 425 | if (request.speed > SCODE_3200) |
420 | return -EINVAL; | 426 | return -EINVAL; |
421 | 427 | ||
@@ -424,6 +430,8 @@ static int ioctl_create_iso_context(struct client *client, void __user *arg) | |||
424 | request.channel, | 430 | request.channel, |
425 | request.speed, | 431 | request.speed, |
426 | request.header_size, | 432 | request.header_size, |
433 | request.sync, | ||
434 | request.tags, | ||
427 | iso_callback, client); | 435 | iso_callback, client); |
428 | if (IS_ERR(client->iso_context)) | 436 | if (IS_ERR(client->iso_context)) |
429 | return PTR_ERR(client->iso_context); | 437 | return PTR_ERR(client->iso_context); |
@@ -495,7 +503,7 @@ static int ioctl_queue_iso(struct client *client, void __user *arg) | |||
495 | if (__copy_from_user | 503 | if (__copy_from_user |
496 | (u.packet.header, p->header, header_length)) | 504 | (u.packet.header, p->header, header_length)) |
497 | return -EFAULT; | 505 | return -EFAULT; |
498 | if (u.packet.skip && | 506 | if (u.packet.skip && ctx->type == FW_ISO_CONTEXT_TRANSMIT && |
499 | u.packet.header_length + u.packet.payload_length > 0) | 507 | u.packet.header_length + u.packet.payload_length > 0) |
500 | return -EINVAL; | 508 | return -EINVAL; |
501 | if (payload + u.packet.payload_length > payload_end) | 509 | if (payload + u.packet.payload_length > payload_end) |
diff --git a/drivers/firewire/fw-device-cdev.h b/drivers/firewire/fw-device-cdev.h index 99e6aa629f4a..739f54fe08cf 100644 --- a/drivers/firewire/fw-device-cdev.h +++ b/drivers/firewire/fw-device-cdev.h | |||
@@ -131,11 +131,19 @@ struct fw_cdev_allocate { | |||
131 | #define FW_CDEV_ISO_CONTEXT_TRANSMIT 0 | 131 | #define FW_CDEV_ISO_CONTEXT_TRANSMIT 0 |
132 | #define FW_CDEV_ISO_CONTEXT_RECEIVE 1 | 132 | #define FW_CDEV_ISO_CONTEXT_RECEIVE 1 |
133 | 133 | ||
134 | #define FW_CDEV_ISO_CONTEXT_MATCH_TAG0 1 | ||
135 | #define FW_CDEV_ISO_CONTEXT_MATCH_TAG1 2 | ||
136 | #define FW_CDEV_ISO_CONTEXT_MATCH_TAG2 4 | ||
137 | #define FW_CDEV_ISO_CONTEXT_MATCH_TAG3 8 | ||
138 | #define FW_CDEV_ISO_CONTEXT_MATCH_ALL_TAGS 15 | ||
139 | |||
134 | struct fw_cdev_create_iso_context { | 140 | struct fw_cdev_create_iso_context { |
135 | __u32 type; | 141 | __u32 type; |
136 | __u32 header_size; | 142 | __u32 header_size; |
137 | __u32 channel; | 143 | __u32 channel; |
138 | __u32 speed; | 144 | __u32 speed; |
145 | __u32 sync; | ||
146 | __u32 tags; | ||
139 | }; | 147 | }; |
140 | 148 | ||
141 | struct fw_cdev_iso_packet { | 149 | struct fw_cdev_iso_packet { |
diff --git a/drivers/firewire/fw-iso.c b/drivers/firewire/fw-iso.c index dc5a7e3558ec..728cbb3ee91d 100644 --- a/drivers/firewire/fw-iso.c +++ b/drivers/firewire/fw-iso.c | |||
@@ -107,12 +107,14 @@ void fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, | |||
107 | 107 | ||
108 | struct fw_iso_context * | 108 | struct fw_iso_context * |
109 | fw_iso_context_create(struct fw_card *card, int type, | 109 | fw_iso_context_create(struct fw_card *card, int type, |
110 | int channel, int speed, size_t header_size, | 110 | int channel, int speed, |
111 | int sync, int tags, size_t header_size, | ||
111 | fw_iso_callback_t callback, void *callback_data) | 112 | fw_iso_callback_t callback, void *callback_data) |
112 | { | 113 | { |
113 | struct fw_iso_context *ctx; | 114 | struct fw_iso_context *ctx; |
114 | 115 | ||
115 | ctx = card->driver->allocate_iso_context(card, type, header_size); | 116 | ctx = card->driver->allocate_iso_context(card, type, |
117 | sync, tags, header_size); | ||
116 | if (IS_ERR(ctx)) | 118 | if (IS_ERR(ctx)) |
117 | return ctx; | 119 | return ctx; |
118 | 120 | ||
@@ -120,6 +122,8 @@ fw_iso_context_create(struct fw_card *card, int type, | |||
120 | ctx->type = type; | 122 | ctx->type = type; |
121 | ctx->channel = channel; | 123 | ctx->channel = channel; |
122 | ctx->speed = speed; | 124 | ctx->speed = speed; |
125 | ctx->sync = sync; | ||
126 | ctx->tags = tags; | ||
123 | ctx->header_size = header_size; | 127 | ctx->header_size = header_size; |
124 | ctx->callback = callback; | 128 | ctx->callback = callback; |
125 | ctx->callback_data = callback_data; | 129 | ctx->callback_data = callback_data; |
diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index 0088acd7718e..ea43a5ed18cf 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c | |||
@@ -1337,7 +1337,8 @@ static int handle_it_packet(struct context *context, | |||
1337 | } | 1337 | } |
1338 | 1338 | ||
1339 | static struct fw_iso_context * | 1339 | static struct fw_iso_context * |
1340 | ohci_allocate_iso_context(struct fw_card *card, int type, size_t header_size) | 1340 | ohci_allocate_iso_context(struct fw_card *card, int type, |
1341 | int sync, int tags, size_t header_size) | ||
1341 | { | 1342 | { |
1342 | struct fw_ohci *ohci = fw_ohci(card); | 1343 | struct fw_ohci *ohci = fw_ohci(card); |
1343 | struct iso_context *ctx, *list; | 1344 | struct iso_context *ctx, *list; |
@@ -1427,7 +1428,8 @@ static int ohci_start_iso(struct fw_iso_context *base, s32 cycle) | |||
1427 | reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 1 << index); | 1428 | reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 1 << index); |
1428 | reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1 << index); | 1429 | reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1 << index); |
1429 | reg_write(ohci, context_match(ctx->context.regs), | 1430 | reg_write(ohci, context_match(ctx->context.regs), |
1430 | 0xf0000000 | ctx->base.channel); | 1431 | (ctx->base.tags << 28) | |
1432 | (ctx->base.sync << 8) | ctx->base.channel); | ||
1431 | context_run(&ctx->context, mode); | 1433 | context_run(&ctx->context, mode); |
1432 | } | 1434 | } |
1433 | 1435 | ||
@@ -1573,6 +1575,26 @@ ohci_queue_iso_transmit(struct fw_iso_context *base, | |||
1573 | 1575 | ||
1574 | return 0; | 1576 | return 0; |
1575 | } | 1577 | } |
1578 | |||
1579 | static int | ||
1580 | setup_wait_descriptor(struct context *ctx) | ||
1581 | { | ||
1582 | struct descriptor *d; | ||
1583 | dma_addr_t d_bus; | ||
1584 | |||
1585 | d = context_get_descriptors(ctx, 1, &d_bus); | ||
1586 | if (d == NULL) | ||
1587 | return -ENOMEM; | ||
1588 | |||
1589 | d->control = cpu_to_le16(descriptor_input_more | | ||
1590 | descriptor_status | | ||
1591 | descriptor_branch_always | | ||
1592 | descriptor_wait); | ||
1593 | |||
1594 | context_append(ctx, d, 1, 0); | ||
1595 | |||
1596 | return 0; | ||
1597 | } | ||
1576 | 1598 | ||
1577 | static int | 1599 | static int |
1578 | ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, | 1600 | ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, |
@@ -1591,6 +1613,9 @@ ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, | |||
1591 | /* FIXME: Cycle lost behavior should be configurable: lose | 1613 | /* FIXME: Cycle lost behavior should be configurable: lose |
1592 | * packet, retransmit or terminate.. */ | 1614 | * packet, retransmit or terminate.. */ |
1593 | 1615 | ||
1616 | if (packet->skip && setup_wait_descriptor(&ctx->context) < 0) | ||
1617 | return -ENOMEM; | ||
1618 | |||
1594 | p = packet; | 1619 | p = packet; |
1595 | z = 2; | 1620 | z = 2; |
1596 | 1621 | ||
@@ -1655,6 +1680,9 @@ ohci_queue_iso_receive_bufferfill(struct fw_iso_context *base, | |||
1655 | offset = payload & ~PAGE_MASK; | 1680 | offset = payload & ~PAGE_MASK; |
1656 | rest = packet->payload_length; | 1681 | rest = packet->payload_length; |
1657 | 1682 | ||
1683 | if (packet->skip && setup_wait_descriptor(&ctx->context) < 0) | ||
1684 | return -ENOMEM; | ||
1685 | |||
1658 | while (rest > 0) { | 1686 | while (rest > 0) { |
1659 | d = context_get_descriptors(&ctx->context, 1, &d_bus); | 1687 | d = context_get_descriptors(&ctx->context, 1, &d_bus); |
1660 | if (d == NULL) | 1688 | if (d == NULL) |
diff --git a/drivers/firewire/fw-transaction.h b/drivers/firewire/fw-transaction.h index 22e45ccd7b1d..cbea845dc40a 100644 --- a/drivers/firewire/fw-transaction.h +++ b/drivers/firewire/fw-transaction.h | |||
@@ -332,6 +332,12 @@ struct fw_iso_packet { | |||
332 | #define FW_ISO_CONTEXT_TRANSMIT 0 | 332 | #define FW_ISO_CONTEXT_TRANSMIT 0 |
333 | #define FW_ISO_CONTEXT_RECEIVE 1 | 333 | #define FW_ISO_CONTEXT_RECEIVE 1 |
334 | 334 | ||
335 | #define FW_ISO_CONTEXT_MATCH_TAG0 1 | ||
336 | #define FW_ISO_CONTEXT_MATCH_TAG1 2 | ||
337 | #define FW_ISO_CONTEXT_MATCH_TAG2 4 | ||
338 | #define FW_ISO_CONTEXT_MATCH_TAG3 8 | ||
339 | #define FW_ISO_CONTEXT_MATCH_ALL_TAGS 15 | ||
340 | |||
335 | struct fw_iso_context; | 341 | struct fw_iso_context; |
336 | 342 | ||
337 | typedef void (*fw_iso_callback_t) (struct fw_iso_context *context, | 343 | typedef void (*fw_iso_callback_t) (struct fw_iso_context *context, |
@@ -357,6 +363,8 @@ struct fw_iso_context { | |||
357 | int type; | 363 | int type; |
358 | int channel; | 364 | int channel; |
359 | int speed; | 365 | int speed; |
366 | int sync; | ||
367 | int tags; | ||
360 | size_t header_size; | 368 | size_t header_size; |
361 | fw_iso_callback_t callback; | 369 | fw_iso_callback_t callback; |
362 | void *callback_data; | 370 | void *callback_data; |
@@ -374,7 +382,8 @@ fw_iso_buffer_destroy(struct fw_iso_buffer *buffer, struct fw_card *card); | |||
374 | 382 | ||
375 | struct fw_iso_context * | 383 | struct fw_iso_context * |
376 | fw_iso_context_create(struct fw_card *card, int type, | 384 | fw_iso_context_create(struct fw_card *card, int type, |
377 | int channel, int speed, size_t header_size, | 385 | int channel, int speed, |
386 | int sync, int tags, size_t header_size, | ||
378 | fw_iso_callback_t callback, void *callback_data); | 387 | fw_iso_callback_t callback, void *callback_data); |
379 | 388 | ||
380 | void | 389 | void |
@@ -425,7 +434,7 @@ struct fw_card_driver { | |||
425 | int node_id, int generation); | 434 | int node_id, int generation); |
426 | 435 | ||
427 | struct fw_iso_context * | 436 | struct fw_iso_context * |
428 | (*allocate_iso_context)(struct fw_card *card, | 437 | (*allocate_iso_context)(struct fw_card *card, int sync, int tags, |
429 | int type, size_t header_size); | 438 | int type, size_t header_size); |
430 | void (*free_iso_context)(struct fw_iso_context *ctx); | 439 | void (*free_iso_context)(struct fw_iso_context *ctx); |
431 | 440 | ||