aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire/fw-device-cdev.c
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2007-02-16 17:34:44 -0500
committerStefan Richter <stefanr@s5r6.in-berlin.de>2007-03-09 16:03:00 -0500
commit9b32d5f3074e9b1afaa39a360a59fd77a2214783 (patch)
tree441cde033cc8a55b7bc9715684c42554fa259cc4 /drivers/firewire/fw-device-cdev.c
parent500be7251a4af1a87aa48285a23a741f74a97a89 (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.c25
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
385static void 385static void
386iso_callback(struct fw_iso_context *context, int status, u32 cycle, void *data) 386iso_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
402static int ioctl_create_iso_context(struct client *client, void __user *arg) 406static 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;