diff options
Diffstat (limited to 'drivers/firewire/fw-device-cdev.c')
-rw-r--r-- | drivers/firewire/fw-device-cdev.c | 278 |
1 files changed, 123 insertions, 155 deletions
diff --git a/drivers/firewire/fw-device-cdev.c b/drivers/firewire/fw-device-cdev.c index fab6dfbcca1b..d2b867f44348 100644 --- a/drivers/firewire/fw-device-cdev.c +++ b/drivers/firewire/fw-device-cdev.c | |||
@@ -258,41 +258,35 @@ void fw_device_cdev_remove(struct fw_device *device) | |||
258 | for_each_client(device, wake_up_client); | 258 | for_each_client(device, wake_up_client); |
259 | } | 259 | } |
260 | 260 | ||
261 | static int ioctl_get_info(struct client *client, void __user *arg) | 261 | static int ioctl_get_info(struct client *client, void *buffer) |
262 | { | 262 | { |
263 | struct fw_cdev_get_info get_info; | 263 | struct fw_cdev_get_info *get_info = buffer; |
264 | struct fw_cdev_event_bus_reset bus_reset; | 264 | struct fw_cdev_event_bus_reset bus_reset; |
265 | 265 | ||
266 | if (copy_from_user(&get_info, arg, sizeof get_info)) | 266 | client->version = get_info->version; |
267 | return -EFAULT; | 267 | get_info->version = FW_CDEV_VERSION; |
268 | |||
269 | client->version = get_info.version; | ||
270 | get_info.version = FW_CDEV_VERSION; | ||
271 | 268 | ||
272 | if (get_info.rom != 0) { | 269 | if (get_info->rom != 0) { |
273 | void __user *uptr = u64_to_uptr(get_info.rom); | 270 | void __user *uptr = u64_to_uptr(get_info->rom); |
274 | size_t want = get_info.rom_length; | 271 | size_t want = get_info->rom_length; |
275 | size_t have = client->device->config_rom_length * 4; | 272 | size_t have = client->device->config_rom_length * 4; |
276 | 273 | ||
277 | if (copy_to_user(uptr, client->device->config_rom, | 274 | if (copy_to_user(uptr, client->device->config_rom, |
278 | min(want, have))) | 275 | min(want, have))) |
279 | return -EFAULT; | 276 | return -EFAULT; |
280 | } | 277 | } |
281 | get_info.rom_length = client->device->config_rom_length * 4; | 278 | get_info->rom_length = client->device->config_rom_length * 4; |
282 | 279 | ||
283 | client->bus_reset_closure = get_info.bus_reset_closure; | 280 | client->bus_reset_closure = get_info->bus_reset_closure; |
284 | if (get_info.bus_reset != 0) { | 281 | if (get_info->bus_reset != 0) { |
285 | void __user *uptr = u64_to_uptr(get_info.bus_reset); | 282 | void __user *uptr = u64_to_uptr(get_info->bus_reset); |
286 | 283 | ||
287 | fill_bus_reset_event(&bus_reset, client); | 284 | fill_bus_reset_event(&bus_reset, client); |
288 | if (copy_to_user(uptr, &bus_reset, sizeof bus_reset)) | 285 | if (copy_to_user(uptr, &bus_reset, sizeof bus_reset)) |
289 | return -EFAULT; | 286 | return -EFAULT; |
290 | } | 287 | } |
291 | 288 | ||
292 | get_info.card = client->device->card->index; | 289 | get_info->card = client->device->card->index; |
293 | |||
294 | if (copy_to_user(arg, &get_info, sizeof get_info)) | ||
295 | return -EFAULT; | ||
296 | 290 | ||
297 | return 0; | 291 | return 0; |
298 | } | 292 | } |
@@ -369,30 +363,27 @@ complete_transaction(struct fw_card *card, int rcode, | |||
369 | response->response.data, response->response.length); | 363 | response->response.data, response->response.length); |
370 | } | 364 | } |
371 | 365 | ||
372 | static ssize_t ioctl_send_request(struct client *client, void __user *arg) | 366 | static ssize_t ioctl_send_request(struct client *client, void *buffer) |
373 | { | 367 | { |
374 | struct fw_device *device = client->device; | 368 | struct fw_device *device = client->device; |
375 | struct fw_cdev_send_request request; | 369 | struct fw_cdev_send_request *request = buffer; |
376 | struct response *response; | 370 | struct response *response; |
377 | 371 | ||
378 | if (copy_from_user(&request, arg, sizeof request)) | ||
379 | return -EFAULT; | ||
380 | |||
381 | /* What is the biggest size we'll accept, really? */ | 372 | /* What is the biggest size we'll accept, really? */ |
382 | if (request.length > 4096) | 373 | if (request->length > 4096) |
383 | return -EINVAL; | 374 | return -EINVAL; |
384 | 375 | ||
385 | response = kmalloc(sizeof *response + request.length, GFP_KERNEL); | 376 | response = kmalloc(sizeof *response + request->length, GFP_KERNEL); |
386 | if (response == NULL) | 377 | if (response == NULL) |
387 | return -ENOMEM; | 378 | return -ENOMEM; |
388 | 379 | ||
389 | response->client = client; | 380 | response->client = client; |
390 | response->response.length = request.length; | 381 | response->response.length = request->length; |
391 | response->response.closure = request.closure; | 382 | response->response.closure = request->closure; |
392 | 383 | ||
393 | if (request.data && | 384 | if (request->data && |
394 | copy_from_user(response->response.data, | 385 | copy_from_user(response->response.data, |
395 | u64_to_uptr(request.data), request.length)) { | 386 | u64_to_uptr(request->data), request->length)) { |
396 | kfree(response); | 387 | kfree(response); |
397 | return -EFAULT; | 388 | return -EFAULT; |
398 | } | 389 | } |
@@ -401,16 +392,16 @@ static ssize_t ioctl_send_request(struct client *client, void __user *arg) | |||
401 | add_client_resource(client, &response->resource); | 392 | add_client_resource(client, &response->resource); |
402 | 393 | ||
403 | fw_send_request(device->card, &response->transaction, | 394 | fw_send_request(device->card, &response->transaction, |
404 | request.tcode & 0x1f, | 395 | request->tcode & 0x1f, |
405 | device->node->node_id, | 396 | device->node->node_id, |
406 | request.generation, | 397 | request->generation, |
407 | device->node->max_speed, | 398 | device->node->max_speed, |
408 | request.offset, | 399 | request->offset, |
409 | response->response.data, request.length, | 400 | response->response.data, request->length, |
410 | complete_transaction, response); | 401 | complete_transaction, response); |
411 | 402 | ||
412 | if (request.data) | 403 | if (request->data) |
413 | return sizeof request + request.length; | 404 | return sizeof request + request->length; |
414 | else | 405 | else |
415 | return sizeof request; | 406 | return sizeof request; |
416 | } | 407 | } |
@@ -495,25 +486,22 @@ release_address_handler(struct client *client, | |||
495 | kfree(handler); | 486 | kfree(handler); |
496 | } | 487 | } |
497 | 488 | ||
498 | static int ioctl_allocate(struct client *client, void __user *arg) | 489 | static int ioctl_allocate(struct client *client, void *buffer) |
499 | { | 490 | { |
500 | struct fw_cdev_allocate request; | 491 | struct fw_cdev_allocate *request = buffer; |
501 | struct address_handler *handler; | 492 | struct address_handler *handler; |
502 | struct fw_address_region region; | 493 | struct fw_address_region region; |
503 | 494 | ||
504 | if (copy_from_user(&request, arg, sizeof request)) | ||
505 | return -EFAULT; | ||
506 | |||
507 | handler = kmalloc(sizeof *handler, GFP_KERNEL); | 495 | handler = kmalloc(sizeof *handler, GFP_KERNEL); |
508 | if (handler == NULL) | 496 | if (handler == NULL) |
509 | return -ENOMEM; | 497 | return -ENOMEM; |
510 | 498 | ||
511 | region.start = request.offset; | 499 | region.start = request->offset; |
512 | region.end = request.offset + request.length; | 500 | region.end = request->offset + request->length; |
513 | handler->handler.length = request.length; | 501 | handler->handler.length = request->length; |
514 | handler->handler.address_callback = handle_request; | 502 | handler->handler.address_callback = handle_request; |
515 | handler->handler.callback_data = handler; | 503 | handler->handler.callback_data = handler; |
516 | handler->closure = request.closure; | 504 | handler->closure = request->closure; |
517 | handler->client = client; | 505 | handler->client = client; |
518 | 506 | ||
519 | if (fw_core_add_address_handler(&handler->handler, ®ion) < 0) { | 507 | if (fw_core_add_address_handler(&handler->handler, ®ion) < 0) { |
@@ -523,55 +511,44 @@ static int ioctl_allocate(struct client *client, void __user *arg) | |||
523 | 511 | ||
524 | handler->resource.release = release_address_handler; | 512 | handler->resource.release = release_address_handler; |
525 | add_client_resource(client, &handler->resource); | 513 | add_client_resource(client, &handler->resource); |
526 | request.handle = handler->resource.handle; | 514 | request->handle = handler->resource.handle; |
527 | |||
528 | if (copy_to_user(arg, &request, sizeof request)) | ||
529 | return -EFAULT; | ||
530 | 515 | ||
531 | return 0; | 516 | return 0; |
532 | } | 517 | } |
533 | 518 | ||
534 | static int ioctl_deallocate(struct client *client, void __user *arg) | 519 | static int ioctl_deallocate(struct client *client, void *buffer) |
535 | { | 520 | { |
536 | struct fw_cdev_deallocate request; | 521 | struct fw_cdev_deallocate *request = buffer; |
537 | |||
538 | if (copy_from_user(&request, arg, sizeof request)) | ||
539 | return -EFAULT; | ||
540 | 522 | ||
541 | return release_client_resource(client, request.handle, NULL); | 523 | return release_client_resource(client, request->handle, NULL); |
542 | } | 524 | } |
543 | 525 | ||
544 | static int ioctl_send_response(struct client *client, void __user *arg) | 526 | static int ioctl_send_response(struct client *client, void *buffer) |
545 | { | 527 | { |
546 | struct fw_cdev_send_response request; | 528 | struct fw_cdev_send_response *request = buffer; |
547 | struct client_resource *resource; | 529 | struct client_resource *resource; |
548 | struct request *r; | 530 | struct request *r; |
549 | 531 | ||
550 | if (copy_from_user(&request, arg, sizeof request)) | 532 | if (release_client_resource(client, request->handle, &resource) < 0) |
551 | return -EFAULT; | ||
552 | if (release_client_resource(client, request.handle, &resource) < 0) | ||
553 | return -EINVAL; | 533 | return -EINVAL; |
554 | r = container_of(resource, struct request, resource); | 534 | r = container_of(resource, struct request, resource); |
555 | if (request.length < r->length) | 535 | if (request->length < r->length) |
556 | r->length = request.length; | 536 | r->length = request->length; |
557 | if (copy_from_user(r->data, u64_to_uptr(request.data), r->length)) | 537 | if (copy_from_user(r->data, u64_to_uptr(request->data), r->length)) |
558 | return -EFAULT; | 538 | return -EFAULT; |
559 | 539 | ||
560 | fw_send_response(client->device->card, r->request, request.rcode); | 540 | fw_send_response(client->device->card, r->request, request->rcode); |
561 | kfree(r); | 541 | kfree(r); |
562 | 542 | ||
563 | return 0; | 543 | return 0; |
564 | } | 544 | } |
565 | 545 | ||
566 | static int ioctl_initiate_bus_reset(struct client *client, void __user *arg) | 546 | static int ioctl_initiate_bus_reset(struct client *client, void *buffer) |
567 | { | 547 | { |
568 | struct fw_cdev_initiate_bus_reset request; | 548 | struct fw_cdev_initiate_bus_reset *request = buffer; |
569 | int short_reset; | 549 | int short_reset; |
570 | 550 | ||
571 | if (copy_from_user(&request, arg, sizeof request)) | 551 | short_reset = (request->type == FW_CDEV_SHORT_RESET); |
572 | return -EFAULT; | ||
573 | |||
574 | short_reset = (request.type == FW_CDEV_SHORT_RESET); | ||
575 | 552 | ||
576 | return fw_core_initiate_bus_reset(client->device->card, short_reset); | 553 | return fw_core_initiate_bus_reset(client->device->card, short_reset); |
577 | } | 554 | } |
@@ -592,32 +569,29 @@ static void release_descriptor(struct client *client, | |||
592 | kfree(descriptor); | 569 | kfree(descriptor); |
593 | } | 570 | } |
594 | 571 | ||
595 | static int ioctl_add_descriptor(struct client *client, void __user *arg) | 572 | static int ioctl_add_descriptor(struct client *client, void *buffer) |
596 | { | 573 | { |
597 | struct fw_cdev_add_descriptor request; | 574 | struct fw_cdev_add_descriptor *request = buffer; |
598 | struct descriptor *descriptor; | 575 | struct descriptor *descriptor; |
599 | int retval; | 576 | int retval; |
600 | 577 | ||
601 | if (copy_from_user(&request, arg, sizeof request)) | 578 | if (request->length > 256) |
602 | return -EFAULT; | ||
603 | |||
604 | if (request.length > 256) | ||
605 | return -EINVAL; | 579 | return -EINVAL; |
606 | 580 | ||
607 | descriptor = | 581 | descriptor = |
608 | kmalloc(sizeof *descriptor + request.length * 4, GFP_KERNEL); | 582 | kmalloc(sizeof *descriptor + request->length * 4, GFP_KERNEL); |
609 | if (descriptor == NULL) | 583 | if (descriptor == NULL) |
610 | return -ENOMEM; | 584 | return -ENOMEM; |
611 | 585 | ||
612 | if (copy_from_user(descriptor->data, | 586 | if (copy_from_user(descriptor->data, |
613 | u64_to_uptr(request.data), request.length * 4)) { | 587 | u64_to_uptr(request->data), request->length * 4)) { |
614 | kfree(descriptor); | 588 | kfree(descriptor); |
615 | return -EFAULT; | 589 | return -EFAULT; |
616 | } | 590 | } |
617 | 591 | ||
618 | descriptor->d.length = request.length; | 592 | descriptor->d.length = request->length; |
619 | descriptor->d.immediate = request.immediate; | 593 | descriptor->d.immediate = request->immediate; |
620 | descriptor->d.key = request.key; | 594 | descriptor->d.key = request->key; |
621 | descriptor->d.data = descriptor->data; | 595 | descriptor->d.data = descriptor->data; |
622 | 596 | ||
623 | retval = fw_core_add_descriptor(&descriptor->d); | 597 | retval = fw_core_add_descriptor(&descriptor->d); |
@@ -628,22 +602,16 @@ static int ioctl_add_descriptor(struct client *client, void __user *arg) | |||
628 | 602 | ||
629 | descriptor->resource.release = release_descriptor; | 603 | descriptor->resource.release = release_descriptor; |
630 | add_client_resource(client, &descriptor->resource); | 604 | add_client_resource(client, &descriptor->resource); |
631 | request.handle = descriptor->resource.handle; | 605 | request->handle = descriptor->resource.handle; |
632 | |||
633 | if (copy_to_user(arg, &request, sizeof request)) | ||
634 | return -EFAULT; | ||
635 | 606 | ||
636 | return 0; | 607 | return 0; |
637 | } | 608 | } |
638 | 609 | ||
639 | static int ioctl_remove_descriptor(struct client *client, void __user *arg) | 610 | static int ioctl_remove_descriptor(struct client *client, void *buffer) |
640 | { | 611 | { |
641 | struct fw_cdev_remove_descriptor request; | 612 | struct fw_cdev_remove_descriptor *request = buffer; |
642 | 613 | ||
643 | if (copy_from_user(&request, arg, sizeof request)) | 614 | return release_client_resource(client, request->handle, NULL); |
644 | return -EFAULT; | ||
645 | |||
646 | return release_client_resource(client, request.handle, NULL); | ||
647 | } | 615 | } |
648 | 616 | ||
649 | static void | 617 | static void |
@@ -667,25 +635,22 @@ iso_callback(struct fw_iso_context *context, u32 cycle, | |||
667 | sizeof interrupt->interrupt + header_length, NULL, 0); | 635 | sizeof interrupt->interrupt + header_length, NULL, 0); |
668 | } | 636 | } |
669 | 637 | ||
670 | static int ioctl_create_iso_context(struct client *client, void __user *arg) | 638 | static int ioctl_create_iso_context(struct client *client, void *buffer) |
671 | { | 639 | { |
672 | struct fw_cdev_create_iso_context request; | 640 | struct fw_cdev_create_iso_context *request = buffer; |
673 | 641 | ||
674 | if (copy_from_user(&request, arg, sizeof request)) | 642 | if (request->channel > 63) |
675 | return -EFAULT; | ||
676 | |||
677 | if (request.channel > 63) | ||
678 | return -EINVAL; | 643 | return -EINVAL; |
679 | 644 | ||
680 | switch (request.type) { | 645 | switch (request->type) { |
681 | case FW_ISO_CONTEXT_RECEIVE: | 646 | case FW_ISO_CONTEXT_RECEIVE: |
682 | if (request.header_size < 4 || (request.header_size & 3)) | 647 | if (request->header_size < 4 || (request->header_size & 3)) |
683 | return -EINVAL; | 648 | return -EINVAL; |
684 | 649 | ||
685 | break; | 650 | break; |
686 | 651 | ||
687 | case FW_ISO_CONTEXT_TRANSMIT: | 652 | case FW_ISO_CONTEXT_TRANSMIT: |
688 | if (request.speed > SCODE_3200) | 653 | if (request->speed > SCODE_3200) |
689 | return -EINVAL; | 654 | return -EINVAL; |
690 | 655 | ||
691 | break; | 656 | break; |
@@ -695,10 +660,10 @@ static int ioctl_create_iso_context(struct client *client, void __user *arg) | |||
695 | } | 660 | } |
696 | 661 | ||
697 | client->iso_context = fw_iso_context_create(client->device->card, | 662 | client->iso_context = fw_iso_context_create(client->device->card, |
698 | request.type, | 663 | request->type, |
699 | request.channel, | 664 | request->channel, |
700 | request.speed, | 665 | request->speed, |
701 | request.header_size, | 666 | request->header_size, |
702 | iso_callback, client); | 667 | iso_callback, client); |
703 | if (IS_ERR(client->iso_context)) | 668 | if (IS_ERR(client->iso_context)) |
704 | return PTR_ERR(client->iso_context); | 669 | return PTR_ERR(client->iso_context); |
@@ -706,9 +671,9 @@ static int ioctl_create_iso_context(struct client *client, void __user *arg) | |||
706 | return 0; | 671 | return 0; |
707 | } | 672 | } |
708 | 673 | ||
709 | static int ioctl_queue_iso(struct client *client, void __user *arg) | 674 | static int ioctl_queue_iso(struct client *client, void *buffer) |
710 | { | 675 | { |
711 | struct fw_cdev_queue_iso request; | 676 | struct fw_cdev_queue_iso *request = buffer; |
712 | struct fw_cdev_iso_packet __user *p, *end, *next; | 677 | struct fw_cdev_iso_packet __user *p, *end, *next; |
713 | struct fw_iso_context *ctx = client->iso_context; | 678 | struct fw_iso_context *ctx = client->iso_context; |
714 | unsigned long payload, buffer_end, header_length; | 679 | unsigned long payload, buffer_end, header_length; |
@@ -720,8 +685,6 @@ static int ioctl_queue_iso(struct client *client, void __user *arg) | |||
720 | 685 | ||
721 | if (ctx == NULL) | 686 | if (ctx == NULL) |
722 | return -EINVAL; | 687 | return -EINVAL; |
723 | if (copy_from_user(&request, arg, sizeof request)) | ||
724 | return -EFAULT; | ||
725 | 688 | ||
726 | /* If the user passes a non-NULL data pointer, has mmap()'ed | 689 | /* If the user passes a non-NULL data pointer, has mmap()'ed |
727 | * the iso buffer, and the pointer points inside the buffer, | 690 | * the iso buffer, and the pointer points inside the buffer, |
@@ -729,21 +692,21 @@ static int ioctl_queue_iso(struct client *client, void __user *arg) | |||
729 | * set them both to 0, which will still let packets with | 692 | * set them both to 0, which will still let packets with |
730 | * payload_length == 0 through. In other words, if no packets | 693 | * payload_length == 0 through. In other words, if no packets |
731 | * use the indirect payload, the iso buffer need not be mapped | 694 | * use the indirect payload, the iso buffer need not be mapped |
732 | * and the request.data pointer is ignored.*/ | 695 | * and the request->data pointer is ignored.*/ |
733 | 696 | ||
734 | payload = (unsigned long)request.data - client->vm_start; | 697 | payload = (unsigned long)request->data - client->vm_start; |
735 | buffer_end = client->buffer.page_count << PAGE_SHIFT; | 698 | buffer_end = client->buffer.page_count << PAGE_SHIFT; |
736 | if (request.data == 0 || client->buffer.pages == NULL || | 699 | if (request->data == 0 || client->buffer.pages == NULL || |
737 | payload >= buffer_end) { | 700 | payload >= buffer_end) { |
738 | payload = 0; | 701 | payload = 0; |
739 | buffer_end = 0; | 702 | buffer_end = 0; |
740 | } | 703 | } |
741 | 704 | ||
742 | if (!access_ok(VERIFY_READ, request.packets, request.size)) | 705 | if (!access_ok(VERIFY_READ, request->packets, request->size)) |
743 | return -EFAULT; | 706 | return -EFAULT; |
744 | 707 | ||
745 | p = (struct fw_cdev_iso_packet __user *)u64_to_uptr(request.packets); | 708 | p = (struct fw_cdev_iso_packet __user *)u64_to_uptr(request->packets); |
746 | end = (void __user *)p + request.size; | 709 | end = (void __user *)p + request->size; |
747 | count = 0; | 710 | count = 0; |
748 | while (p < end) { | 711 | while (p < end) { |
749 | if (__copy_from_user(&u.packet, p, sizeof *p)) | 712 | if (__copy_from_user(&u.packet, p, sizeof *p)) |
@@ -785,71 +748,76 @@ static int ioctl_queue_iso(struct client *client, void __user *arg) | |||
785 | count++; | 748 | count++; |
786 | } | 749 | } |
787 | 750 | ||
788 | request.size -= uptr_to_u64(p) - request.packets; | 751 | request->size -= uptr_to_u64(p) - request->packets; |
789 | request.packets = uptr_to_u64(p); | 752 | request->packets = uptr_to_u64(p); |
790 | request.data = client->vm_start + payload; | 753 | request->data = client->vm_start + payload; |
791 | |||
792 | if (copy_to_user(arg, &request, sizeof request)) | ||
793 | return -EFAULT; | ||
794 | 754 | ||
795 | return count; | 755 | return count; |
796 | } | 756 | } |
797 | 757 | ||
798 | static int ioctl_start_iso(struct client *client, void __user *arg) | 758 | static int ioctl_start_iso(struct client *client, void *buffer) |
799 | { | 759 | { |
800 | struct fw_cdev_start_iso request; | 760 | struct fw_cdev_start_iso *request = buffer; |
801 | |||
802 | if (copy_from_user(&request, arg, sizeof request)) | ||
803 | return -EFAULT; | ||
804 | 761 | ||
805 | if (client->iso_context->type == FW_ISO_CONTEXT_RECEIVE) { | 762 | if (client->iso_context->type == FW_ISO_CONTEXT_RECEIVE) { |
806 | if (request.tags == 0 || request.tags > 15) | 763 | if (request->tags == 0 || request->tags > 15) |
807 | return -EINVAL; | 764 | return -EINVAL; |
808 | 765 | ||
809 | if (request.sync > 15) | 766 | if (request->sync > 15) |
810 | return -EINVAL; | 767 | return -EINVAL; |
811 | } | 768 | } |
812 | 769 | ||
813 | return fw_iso_context_start(client->iso_context, | 770 | return fw_iso_context_start(client->iso_context, request->cycle, |
814 | request.cycle, request.sync, request.tags); | 771 | request->sync, request->tags); |
815 | } | 772 | } |
816 | 773 | ||
817 | static int ioctl_stop_iso(struct client *client, void __user *arg) | 774 | static int ioctl_stop_iso(struct client *client, void *buffer) |
818 | { | 775 | { |
819 | return fw_iso_context_stop(client->iso_context); | 776 | return fw_iso_context_stop(client->iso_context); |
820 | } | 777 | } |
821 | 778 | ||
779 | static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { | ||
780 | ioctl_get_info, | ||
781 | ioctl_send_request, | ||
782 | ioctl_allocate, | ||
783 | ioctl_deallocate, | ||
784 | ioctl_send_response, | ||
785 | ioctl_initiate_bus_reset, | ||
786 | ioctl_add_descriptor, | ||
787 | ioctl_remove_descriptor, | ||
788 | ioctl_create_iso_context, | ||
789 | ioctl_queue_iso, | ||
790 | ioctl_start_iso, | ||
791 | ioctl_stop_iso, | ||
792 | }; | ||
793 | |||
822 | static int | 794 | static int |
823 | dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg) | 795 | dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg) |
824 | { | 796 | { |
825 | switch (cmd) { | 797 | char buffer[256]; |
826 | case FW_CDEV_IOC_GET_INFO: | 798 | int retval; |
827 | return ioctl_get_info(client, arg); | 799 | |
828 | case FW_CDEV_IOC_SEND_REQUEST: | 800 | if (_IOC_TYPE(cmd) != '#' || |
829 | return ioctl_send_request(client, arg); | 801 | _IOC_NR(cmd) >= ARRAY_SIZE(ioctl_handlers)) |
830 | case FW_CDEV_IOC_ALLOCATE: | ||
831 | return ioctl_allocate(client, arg); | ||
832 | case FW_CDEV_IOC_DEALLOCATE: | ||
833 | return ioctl_deallocate(client, arg); | ||
834 | case FW_CDEV_IOC_SEND_RESPONSE: | ||
835 | return ioctl_send_response(client, arg); | ||
836 | case FW_CDEV_IOC_INITIATE_BUS_RESET: | ||
837 | return ioctl_initiate_bus_reset(client, arg); | ||
838 | case FW_CDEV_IOC_ADD_DESCRIPTOR: | ||
839 | return ioctl_add_descriptor(client, arg); | ||
840 | case FW_CDEV_IOC_REMOVE_DESCRIPTOR: | ||
841 | return ioctl_remove_descriptor(client, arg); | ||
842 | case FW_CDEV_IOC_CREATE_ISO_CONTEXT: | ||
843 | return ioctl_create_iso_context(client, arg); | ||
844 | case FW_CDEV_IOC_QUEUE_ISO: | ||
845 | return ioctl_queue_iso(client, arg); | ||
846 | case FW_CDEV_IOC_START_ISO: | ||
847 | return ioctl_start_iso(client, arg); | ||
848 | case FW_CDEV_IOC_STOP_ISO: | ||
849 | return ioctl_stop_iso(client, arg); | ||
850 | default: | ||
851 | return -EINVAL; | 802 | return -EINVAL; |
803 | |||
804 | if (_IOC_DIR(cmd) & _IOC_WRITE) { | ||
805 | if (_IOC_SIZE(cmd) > sizeof buffer || | ||
806 | copy_from_user(buffer, arg, _IOC_SIZE(cmd))) | ||
807 | return -EFAULT; | ||
808 | } | ||
809 | |||
810 | retval = ioctl_handlers[_IOC_NR(cmd)](client, buffer); | ||
811 | if (retval < 0) | ||
812 | return retval; | ||
813 | |||
814 | if (_IOC_DIR(cmd) & _IOC_READ) { | ||
815 | if (_IOC_SIZE(cmd) > sizeof buffer || | ||
816 | copy_to_user(arg, buffer, _IOC_SIZE(cmd))) | ||
817 | return -EFAULT; | ||
852 | } | 818 | } |
819 | |||
820 | return 0; | ||
853 | } | 821 | } |
854 | 822 | ||
855 | static long | 823 | static long |