diff options
author | Kristian Høgsberg <krh@redhat.com> | 2007-02-16 17:34:44 -0500 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2007-03-09 16:03:00 -0500 |
commit | 9b32d5f3074e9b1afaa39a360a59fd77a2214783 (patch) | |
tree | 441cde033cc8a55b7bc9715684c42554fa259cc4 /drivers/firewire/fw-device-cdev.c | |
parent | 500be7251a4af1a87aa48285a23a741f74a97a89 (diff) |
firewire: Acummulate received iso headers and send them back to user space.
Signed-off-by: Kristian Høgsberg <krh@redhat.com>
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire/fw-device-cdev.c')
-rw-r--r-- | drivers/firewire/fw-device-cdev.c | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/drivers/firewire/fw-device-cdev.c b/drivers/firewire/fw-device-cdev.c index 1ce33d4f91a3..6545fb8214d8 100644 --- a/drivers/firewire/fw-device-cdev.c +++ b/drivers/firewire/fw-device-cdev.c | |||
@@ -383,20 +383,24 @@ static int ioctl_send_response(struct client *client, void __user *arg) | |||
383 | } | 383 | } |
384 | 384 | ||
385 | static void | 385 | static void |
386 | iso_callback(struct fw_iso_context *context, int status, u32 cycle, void *data) | 386 | iso_callback(struct fw_iso_context *context, u32 cycle, |
387 | size_t header_length, void *header, void *data) | ||
387 | { | 388 | { |
388 | struct client *client = data; | 389 | struct client *client = data; |
389 | struct iso_interrupt *interrupt; | 390 | struct iso_interrupt *interrupt; |
390 | 391 | ||
391 | interrupt = kzalloc(sizeof *interrupt, GFP_ATOMIC); | 392 | interrupt = kzalloc(sizeof *interrupt + header_length, GFP_ATOMIC); |
392 | if (interrupt == NULL) | 393 | if (interrupt == NULL) |
393 | return; | 394 | return; |
394 | 395 | ||
395 | interrupt->interrupt.type = FW_CDEV_EVENT_ISO_INTERRUPT; | 396 | interrupt->interrupt.type = FW_CDEV_EVENT_ISO_INTERRUPT; |
396 | interrupt->interrupt.closure = 0; | 397 | interrupt->interrupt.closure = 0; |
397 | interrupt->interrupt.cycle = cycle; | 398 | interrupt->interrupt.cycle = cycle; |
399 | interrupt->interrupt.header_length = header_length; | ||
400 | memcpy(interrupt->interrupt.header, header, header_length); | ||
398 | queue_event(client, &interrupt->event, | 401 | queue_event(client, &interrupt->event, |
399 | &interrupt->interrupt, sizeof interrupt->interrupt, NULL, 0); | 402 | &interrupt->interrupt, |
403 | sizeof interrupt->interrupt + header_length, NULL, 0); | ||
400 | } | 404 | } |
401 | 405 | ||
402 | static int ioctl_create_iso_context(struct client *client, void __user *arg) | 406 | static int ioctl_create_iso_context(struct client *client, void __user *arg) |
@@ -423,6 +427,7 @@ static int ioctl_queue_iso(struct client *client, void __user *arg) | |||
423 | { | 427 | { |
424 | struct fw_cdev_queue_iso request; | 428 | struct fw_cdev_queue_iso request; |
425 | struct fw_cdev_iso_packet __user *p, *end, *next; | 429 | struct fw_cdev_iso_packet __user *p, *end, *next; |
430 | struct fw_iso_context *ctx = client->iso_context; | ||
426 | unsigned long payload, payload_end, header_length; | 431 | unsigned long payload, payload_end, header_length; |
427 | int count; | 432 | int count; |
428 | struct { | 433 | struct { |
@@ -430,7 +435,7 @@ static int ioctl_queue_iso(struct client *client, void __user *arg) | |||
430 | u8 header[256]; | 435 | u8 header[256]; |
431 | } u; | 436 | } u; |
432 | 437 | ||
433 | if (client->iso_context == NULL) | 438 | if (ctx == NULL) |
434 | return -EINVAL; | 439 | return -EINVAL; |
435 | if (copy_from_user(&request, arg, sizeof request)) | 440 | if (copy_from_user(&request, arg, sizeof request)) |
436 | return -EFAULT; | 441 | return -EFAULT; |
@@ -461,13 +466,17 @@ static int ioctl_queue_iso(struct client *client, void __user *arg) | |||
461 | if (__copy_from_user(&u.packet, p, sizeof *p)) | 466 | if (__copy_from_user(&u.packet, p, sizeof *p)) |
462 | return -EFAULT; | 467 | return -EFAULT; |
463 | 468 | ||
464 | if (client->iso_context->type == FW_ISO_CONTEXT_TRANSMIT) { | 469 | if (ctx->type == FW_ISO_CONTEXT_TRANSMIT) { |
465 | header_length = u.packet.header_length; | 470 | header_length = u.packet.header_length; |
466 | } else { | 471 | } else { |
467 | /* We require that header_length is a multiple of | 472 | /* We require that header_length is a multiple of |
468 | * the fixed header size, ctx->header_size */ | 473 | * the fixed header size, ctx->header_size */ |
469 | if (u.packet.header_length % client->iso_context->header_size != 0) | 474 | if (ctx->header_size == 0) { |
475 | if (u.packet.header_length > 0) | ||
476 | return -EINVAL; | ||
477 | } else if (u.packet.header_length % ctx->header_size != 0) { | ||
470 | return -EINVAL; | 478 | return -EINVAL; |
479 | } | ||
471 | header_length = 0; | 480 | header_length = 0; |
472 | } | 481 | } |
473 | 482 | ||
@@ -484,8 +493,8 @@ static int ioctl_queue_iso(struct client *client, void __user *arg) | |||
484 | if (payload + u.packet.payload_length > payload_end) | 493 | if (payload + u.packet.payload_length > payload_end) |
485 | return -EINVAL; | 494 | return -EINVAL; |
486 | 495 | ||
487 | if (fw_iso_context_queue(client->iso_context, | 496 | if (fw_iso_context_queue(ctx, &u.packet, |
488 | &u.packet, &client->buffer, payload)) | 497 | &client->buffer, payload)) |
489 | break; | 498 | break; |
490 | 499 | ||
491 | p = next; | 500 | p = next; |