diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/firewire/core-cdev.c | 325 |
1 files changed, 152 insertions, 173 deletions
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index a4aa477b9b2c..d7de17a0f250 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c | |||
@@ -368,39 +368,56 @@ void fw_device_cdev_remove(struct fw_device *device) | |||
368 | for_each_client(device, wake_up_client); | 368 | for_each_client(device, wake_up_client); |
369 | } | 369 | } |
370 | 370 | ||
371 | static int ioctl_get_info(struct client *client, void *buffer) | 371 | union ioctl_arg { |
372 | struct fw_cdev_get_info get_info; | ||
373 | struct fw_cdev_send_request send_request; | ||
374 | struct fw_cdev_allocate allocate; | ||
375 | struct fw_cdev_deallocate deallocate; | ||
376 | struct fw_cdev_send_response send_response; | ||
377 | struct fw_cdev_initiate_bus_reset initiate_bus_reset; | ||
378 | struct fw_cdev_add_descriptor add_descriptor; | ||
379 | struct fw_cdev_remove_descriptor remove_descriptor; | ||
380 | struct fw_cdev_create_iso_context create_iso_context; | ||
381 | struct fw_cdev_queue_iso queue_iso; | ||
382 | struct fw_cdev_start_iso start_iso; | ||
383 | struct fw_cdev_stop_iso stop_iso; | ||
384 | struct fw_cdev_get_cycle_timer get_cycle_timer; | ||
385 | struct fw_cdev_allocate_iso_resource allocate_iso_resource; | ||
386 | struct fw_cdev_send_stream_packet send_stream_packet; | ||
387 | struct fw_cdev_get_cycle_timer2 get_cycle_timer2; | ||
388 | }; | ||
389 | |||
390 | static int ioctl_get_info(struct client *client, union ioctl_arg *arg) | ||
372 | { | 391 | { |
373 | struct fw_cdev_get_info *get_info = buffer; | 392 | struct fw_cdev_get_info *a = &arg->get_info; |
374 | struct fw_cdev_event_bus_reset bus_reset; | 393 | struct fw_cdev_event_bus_reset bus_reset; |
375 | unsigned long ret = 0; | 394 | unsigned long ret = 0; |
376 | 395 | ||
377 | client->version = get_info->version; | 396 | client->version = a->version; |
378 | get_info->version = FW_CDEV_VERSION; | 397 | a->version = FW_CDEV_VERSION; |
379 | get_info->card = client->device->card->index; | 398 | a->card = client->device->card->index; |
380 | 399 | ||
381 | down_read(&fw_device_rwsem); | 400 | down_read(&fw_device_rwsem); |
382 | 401 | ||
383 | if (get_info->rom != 0) { | 402 | if (a->rom != 0) { |
384 | void __user *uptr = u64_to_uptr(get_info->rom); | 403 | size_t want = a->rom_length; |
385 | size_t want = get_info->rom_length; | ||
386 | size_t have = client->device->config_rom_length * 4; | 404 | size_t have = client->device->config_rom_length * 4; |
387 | 405 | ||
388 | ret = copy_to_user(uptr, client->device->config_rom, | 406 | ret = copy_to_user(u64_to_uptr(a->rom), |
389 | min(want, have)); | 407 | client->device->config_rom, min(want, have)); |
390 | } | 408 | } |
391 | get_info->rom_length = client->device->config_rom_length * 4; | 409 | a->rom_length = client->device->config_rom_length * 4; |
392 | 410 | ||
393 | up_read(&fw_device_rwsem); | 411 | up_read(&fw_device_rwsem); |
394 | 412 | ||
395 | if (ret != 0) | 413 | if (ret != 0) |
396 | return -EFAULT; | 414 | return -EFAULT; |
397 | 415 | ||
398 | client->bus_reset_closure = get_info->bus_reset_closure; | 416 | client->bus_reset_closure = a->bus_reset_closure; |
399 | if (get_info->bus_reset != 0) { | 417 | if (a->bus_reset != 0) { |
400 | void __user *uptr = u64_to_uptr(get_info->bus_reset); | ||
401 | |||
402 | fill_bus_reset_event(&bus_reset, client); | 418 | fill_bus_reset_event(&bus_reset, client); |
403 | if (copy_to_user(uptr, &bus_reset, sizeof(bus_reset))) | 419 | if (copy_to_user(u64_to_uptr(a->bus_reset), |
420 | &bus_reset, sizeof(bus_reset))) | ||
404 | return -EFAULT; | 421 | return -EFAULT; |
405 | } | 422 | } |
406 | 423 | ||
@@ -571,11 +588,9 @@ static int init_request(struct client *client, | |||
571 | return ret; | 588 | return ret; |
572 | } | 589 | } |
573 | 590 | ||
574 | static int ioctl_send_request(struct client *client, void *buffer) | 591 | static int ioctl_send_request(struct client *client, union ioctl_arg *arg) |
575 | { | 592 | { |
576 | struct fw_cdev_send_request *request = buffer; | 593 | switch (arg->send_request.tcode) { |
577 | |||
578 | switch (request->tcode) { | ||
579 | case TCODE_WRITE_QUADLET_REQUEST: | 594 | case TCODE_WRITE_QUADLET_REQUEST: |
580 | case TCODE_WRITE_BLOCK_REQUEST: | 595 | case TCODE_WRITE_BLOCK_REQUEST: |
581 | case TCODE_READ_QUADLET_REQUEST: | 596 | case TCODE_READ_QUADLET_REQUEST: |
@@ -592,7 +607,7 @@ static int ioctl_send_request(struct client *client, void *buffer) | |||
592 | return -EINVAL; | 607 | return -EINVAL; |
593 | } | 608 | } |
594 | 609 | ||
595 | return init_request(client, request, client->device->node_id, | 610 | return init_request(client, &arg->send_request, client->device->node_id, |
596 | client->device->max_speed); | 611 | client->device->max_speed); |
597 | } | 612 | } |
598 | 613 | ||
@@ -683,9 +698,9 @@ static void release_address_handler(struct client *client, | |||
683 | kfree(r); | 698 | kfree(r); |
684 | } | 699 | } |
685 | 700 | ||
686 | static int ioctl_allocate(struct client *client, void *buffer) | 701 | static int ioctl_allocate(struct client *client, union ioctl_arg *arg) |
687 | { | 702 | { |
688 | struct fw_cdev_allocate *request = buffer; | 703 | struct fw_cdev_allocate *a = &arg->allocate; |
689 | struct address_handler_resource *r; | 704 | struct address_handler_resource *r; |
690 | struct fw_address_region region; | 705 | struct fw_address_region region; |
691 | int ret; | 706 | int ret; |
@@ -694,13 +709,13 @@ static int ioctl_allocate(struct client *client, void *buffer) | |||
694 | if (r == NULL) | 709 | if (r == NULL) |
695 | return -ENOMEM; | 710 | return -ENOMEM; |
696 | 711 | ||
697 | region.start = request->offset; | 712 | region.start = a->offset; |
698 | region.end = request->offset + request->length; | 713 | region.end = a->offset + a->length; |
699 | r->handler.length = request->length; | 714 | r->handler.length = a->length; |
700 | r->handler.address_callback = handle_request; | 715 | r->handler.address_callback = handle_request; |
701 | r->handler.callback_data = r; | 716 | r->handler.callback_data = r; |
702 | r->closure = request->closure; | 717 | r->closure = a->closure; |
703 | r->client = client; | 718 | r->client = client; |
704 | 719 | ||
705 | ret = fw_core_add_address_handler(&r->handler, ®ion); | 720 | ret = fw_core_add_address_handler(&r->handler, ®ion); |
706 | if (ret < 0) { | 721 | if (ret < 0) { |
@@ -714,27 +729,25 @@ static int ioctl_allocate(struct client *client, void *buffer) | |||
714 | release_address_handler(client, &r->resource); | 729 | release_address_handler(client, &r->resource); |
715 | return ret; | 730 | return ret; |
716 | } | 731 | } |
717 | request->handle = r->resource.handle; | 732 | a->handle = r->resource.handle; |
718 | 733 | ||
719 | return 0; | 734 | return 0; |
720 | } | 735 | } |
721 | 736 | ||
722 | static int ioctl_deallocate(struct client *client, void *buffer) | 737 | static int ioctl_deallocate(struct client *client, union ioctl_arg *arg) |
723 | { | 738 | { |
724 | struct fw_cdev_deallocate *request = buffer; | 739 | return release_client_resource(client, arg->deallocate.handle, |
725 | |||
726 | return release_client_resource(client, request->handle, | ||
727 | release_address_handler, NULL); | 740 | release_address_handler, NULL); |
728 | } | 741 | } |
729 | 742 | ||
730 | static int ioctl_send_response(struct client *client, void *buffer) | 743 | static int ioctl_send_response(struct client *client, union ioctl_arg *arg) |
731 | { | 744 | { |
732 | struct fw_cdev_send_response *request = buffer; | 745 | struct fw_cdev_send_response *a = &arg->send_response; |
733 | struct client_resource *resource; | 746 | struct client_resource *resource; |
734 | struct inbound_transaction_resource *r; | 747 | struct inbound_transaction_resource *r; |
735 | int ret = 0; | 748 | int ret = 0; |
736 | 749 | ||
737 | if (release_client_resource(client, request->handle, | 750 | if (release_client_resource(client, a->handle, |
738 | release_request, &resource) < 0) | 751 | release_request, &resource) < 0) |
739 | return -EINVAL; | 752 | return -EINVAL; |
740 | 753 | ||
@@ -743,28 +756,24 @@ static int ioctl_send_response(struct client *client, void *buffer) | |||
743 | if (is_fcp_request(r->request)) | 756 | if (is_fcp_request(r->request)) |
744 | goto out; | 757 | goto out; |
745 | 758 | ||
746 | if (request->length < r->length) | 759 | if (a->length < r->length) |
747 | r->length = request->length; | 760 | r->length = a->length; |
748 | if (copy_from_user(r->data, u64_to_uptr(request->data), r->length)) { | 761 | if (copy_from_user(r->data, u64_to_uptr(a->data), r->length)) { |
749 | ret = -EFAULT; | 762 | ret = -EFAULT; |
750 | kfree(r->request); | 763 | kfree(r->request); |
751 | goto out; | 764 | goto out; |
752 | } | 765 | } |
753 | fw_send_response(client->device->card, r->request, request->rcode); | 766 | fw_send_response(client->device->card, r->request, a->rcode); |
754 | out: | 767 | out: |
755 | kfree(r); | 768 | kfree(r); |
756 | 769 | ||
757 | return ret; | 770 | return ret; |
758 | } | 771 | } |
759 | 772 | ||
760 | static int ioctl_initiate_bus_reset(struct client *client, void *buffer) | 773 | static int ioctl_initiate_bus_reset(struct client *client, union ioctl_arg *arg) |
761 | { | 774 | { |
762 | struct fw_cdev_initiate_bus_reset *request = buffer; | 775 | return fw_core_initiate_bus_reset(client->device->card, |
763 | int short_reset; | 776 | arg->initiate_bus_reset.type == FW_CDEV_SHORT_RESET); |
764 | |||
765 | short_reset = (request->type == FW_CDEV_SHORT_RESET); | ||
766 | |||
767 | return fw_core_initiate_bus_reset(client->device->card, short_reset); | ||
768 | } | 777 | } |
769 | 778 | ||
770 | static void release_descriptor(struct client *client, | 779 | static void release_descriptor(struct client *client, |
@@ -777,9 +786,9 @@ static void release_descriptor(struct client *client, | |||
777 | kfree(r); | 786 | kfree(r); |
778 | } | 787 | } |
779 | 788 | ||
780 | static int ioctl_add_descriptor(struct client *client, void *buffer) | 789 | static int ioctl_add_descriptor(struct client *client, union ioctl_arg *arg) |
781 | { | 790 | { |
782 | struct fw_cdev_add_descriptor *request = buffer; | 791 | struct fw_cdev_add_descriptor *a = &arg->add_descriptor; |
783 | struct descriptor_resource *r; | 792 | struct descriptor_resource *r; |
784 | int ret; | 793 | int ret; |
785 | 794 | ||
@@ -787,22 +796,21 @@ static int ioctl_add_descriptor(struct client *client, void *buffer) | |||
787 | if (!client->device->is_local) | 796 | if (!client->device->is_local) |
788 | return -ENOSYS; | 797 | return -ENOSYS; |
789 | 798 | ||
790 | if (request->length > 256) | 799 | if (a->length > 256) |
791 | return -EINVAL; | 800 | return -EINVAL; |
792 | 801 | ||
793 | r = kmalloc(sizeof(*r) + request->length * 4, GFP_KERNEL); | 802 | r = kmalloc(sizeof(*r) + a->length * 4, GFP_KERNEL); |
794 | if (r == NULL) | 803 | if (r == NULL) |
795 | return -ENOMEM; | 804 | return -ENOMEM; |
796 | 805 | ||
797 | if (copy_from_user(r->data, | 806 | if (copy_from_user(r->data, u64_to_uptr(a->data), a->length * 4)) { |
798 | u64_to_uptr(request->data), request->length * 4)) { | ||
799 | ret = -EFAULT; | 807 | ret = -EFAULT; |
800 | goto failed; | 808 | goto failed; |
801 | } | 809 | } |
802 | 810 | ||
803 | r->descriptor.length = request->length; | 811 | r->descriptor.length = a->length; |
804 | r->descriptor.immediate = request->immediate; | 812 | r->descriptor.immediate = a->immediate; |
805 | r->descriptor.key = request->key; | 813 | r->descriptor.key = a->key; |
806 | r->descriptor.data = r->data; | 814 | r->descriptor.data = r->data; |
807 | 815 | ||
808 | ret = fw_core_add_descriptor(&r->descriptor); | 816 | ret = fw_core_add_descriptor(&r->descriptor); |
@@ -815,7 +823,7 @@ static int ioctl_add_descriptor(struct client *client, void *buffer) | |||
815 | fw_core_remove_descriptor(&r->descriptor); | 823 | fw_core_remove_descriptor(&r->descriptor); |
816 | goto failed; | 824 | goto failed; |
817 | } | 825 | } |
818 | request->handle = r->resource.handle; | 826 | a->handle = r->resource.handle; |
819 | 827 | ||
820 | return 0; | 828 | return 0; |
821 | failed: | 829 | failed: |
@@ -824,11 +832,9 @@ static int ioctl_add_descriptor(struct client *client, void *buffer) | |||
824 | return ret; | 832 | return ret; |
825 | } | 833 | } |
826 | 834 | ||
827 | static int ioctl_remove_descriptor(struct client *client, void *buffer) | 835 | static int ioctl_remove_descriptor(struct client *client, union ioctl_arg *arg) |
828 | { | 836 | { |
829 | struct fw_cdev_remove_descriptor *request = buffer; | 837 | return release_client_resource(client, arg->remove_descriptor.handle, |
830 | |||
831 | return release_client_resource(client, request->handle, | ||
832 | release_descriptor, NULL); | 838 | release_descriptor, NULL); |
833 | } | 839 | } |
834 | 840 | ||
@@ -851,49 +857,44 @@ static void iso_callback(struct fw_iso_context *context, u32 cycle, | |||
851 | sizeof(e->interrupt) + header_length, NULL, 0); | 857 | sizeof(e->interrupt) + header_length, NULL, 0); |
852 | } | 858 | } |
853 | 859 | ||
854 | static int ioctl_create_iso_context(struct client *client, void *buffer) | 860 | static int ioctl_create_iso_context(struct client *client, union ioctl_arg *arg) |
855 | { | 861 | { |
856 | struct fw_cdev_create_iso_context *request = buffer; | 862 | struct fw_cdev_create_iso_context *a = &arg->create_iso_context; |
857 | struct fw_iso_context *context; | 863 | struct fw_iso_context *context; |
858 | 864 | ||
859 | /* We only support one context at this time. */ | 865 | /* We only support one context at this time. */ |
860 | if (client->iso_context != NULL) | 866 | if (client->iso_context != NULL) |
861 | return -EBUSY; | 867 | return -EBUSY; |
862 | 868 | ||
863 | if (request->channel > 63) | 869 | if (a->channel > 63) |
864 | return -EINVAL; | 870 | return -EINVAL; |
865 | 871 | ||
866 | switch (request->type) { | 872 | switch (a->type) { |
867 | case FW_ISO_CONTEXT_RECEIVE: | 873 | case FW_ISO_CONTEXT_RECEIVE: |
868 | if (request->header_size < 4 || (request->header_size & 3)) | 874 | if (a->header_size < 4 || (a->header_size & 3)) |
869 | return -EINVAL; | 875 | return -EINVAL; |
870 | |||
871 | break; | 876 | break; |
872 | 877 | ||
873 | case FW_ISO_CONTEXT_TRANSMIT: | 878 | case FW_ISO_CONTEXT_TRANSMIT: |
874 | if (request->speed > SCODE_3200) | 879 | if (a->speed > SCODE_3200) |
875 | return -EINVAL; | 880 | return -EINVAL; |
876 | |||
877 | break; | 881 | break; |
878 | 882 | ||
879 | default: | 883 | default: |
880 | return -EINVAL; | 884 | return -EINVAL; |
881 | } | 885 | } |
882 | 886 | ||
883 | context = fw_iso_context_create(client->device->card, | 887 | context = fw_iso_context_create(client->device->card, a->type, |
884 | request->type, | 888 | a->channel, a->speed, a->header_size, |
885 | request->channel, | 889 | iso_callback, client); |
886 | request->speed, | ||
887 | request->header_size, | ||
888 | iso_callback, client); | ||
889 | if (IS_ERR(context)) | 890 | if (IS_ERR(context)) |
890 | return PTR_ERR(context); | 891 | return PTR_ERR(context); |
891 | 892 | ||
892 | client->iso_closure = request->closure; | 893 | client->iso_closure = a->closure; |
893 | client->iso_context = context; | 894 | client->iso_context = context; |
894 | 895 | ||
895 | /* We only support one context at this time. */ | 896 | /* We only support one context at this time. */ |
896 | request->handle = 0; | 897 | a->handle = 0; |
897 | 898 | ||
898 | return 0; | 899 | return 0; |
899 | } | 900 | } |
@@ -906,9 +907,9 @@ static int ioctl_create_iso_context(struct client *client, void *buffer) | |||
906 | #define GET_SY(v) (((v) >> 20) & 0x0f) | 907 | #define GET_SY(v) (((v) >> 20) & 0x0f) |
907 | #define GET_HEADER_LENGTH(v) (((v) >> 24) & 0xff) | 908 | #define GET_HEADER_LENGTH(v) (((v) >> 24) & 0xff) |
908 | 909 | ||
909 | static int ioctl_queue_iso(struct client *client, void *buffer) | 910 | static int ioctl_queue_iso(struct client *client, union ioctl_arg *arg) |
910 | { | 911 | { |
911 | struct fw_cdev_queue_iso *request = buffer; | 912 | struct fw_cdev_queue_iso *a = &arg->queue_iso; |
912 | struct fw_cdev_iso_packet __user *p, *end, *next; | 913 | struct fw_cdev_iso_packet __user *p, *end, *next; |
913 | struct fw_iso_context *ctx = client->iso_context; | 914 | struct fw_iso_context *ctx = client->iso_context; |
914 | unsigned long payload, buffer_end, header_length; | 915 | unsigned long payload, buffer_end, header_length; |
@@ -919,7 +920,7 @@ static int ioctl_queue_iso(struct client *client, void *buffer) | |||
919 | u8 header[256]; | 920 | u8 header[256]; |
920 | } u; | 921 | } u; |
921 | 922 | ||
922 | if (ctx == NULL || request->handle != 0) | 923 | if (ctx == NULL || a->handle != 0) |
923 | return -EINVAL; | 924 | return -EINVAL; |
924 | 925 | ||
925 | /* | 926 | /* |
@@ -929,23 +930,23 @@ static int ioctl_queue_iso(struct client *client, void *buffer) | |||
929 | * set them both to 0, which will still let packets with | 930 | * set them both to 0, which will still let packets with |
930 | * payload_length == 0 through. In other words, if no packets | 931 | * payload_length == 0 through. In other words, if no packets |
931 | * use the indirect payload, the iso buffer need not be mapped | 932 | * use the indirect payload, the iso buffer need not be mapped |
932 | * and the request->data pointer is ignored. | 933 | * and the a->data pointer is ignored. |
933 | */ | 934 | */ |
934 | 935 | ||
935 | payload = (unsigned long)request->data - client->vm_start; | 936 | payload = (unsigned long)a->data - client->vm_start; |
936 | buffer_end = client->buffer.page_count << PAGE_SHIFT; | 937 | buffer_end = client->buffer.page_count << PAGE_SHIFT; |
937 | if (request->data == 0 || client->buffer.pages == NULL || | 938 | if (a->data == 0 || client->buffer.pages == NULL || |
938 | payload >= buffer_end) { | 939 | payload >= buffer_end) { |
939 | payload = 0; | 940 | payload = 0; |
940 | buffer_end = 0; | 941 | buffer_end = 0; |
941 | } | 942 | } |
942 | 943 | ||
943 | p = (struct fw_cdev_iso_packet __user *)u64_to_uptr(request->packets); | 944 | p = (struct fw_cdev_iso_packet __user *)u64_to_uptr(a->packets); |
944 | 945 | ||
945 | if (!access_ok(VERIFY_READ, p, request->size)) | 946 | if (!access_ok(VERIFY_READ, p, a->size)) |
946 | return -EFAULT; | 947 | return -EFAULT; |
947 | 948 | ||
948 | end = (void __user *)p + request->size; | 949 | end = (void __user *)p + a->size; |
949 | count = 0; | 950 | count = 0; |
950 | while (p < end) { | 951 | while (p < end) { |
951 | if (get_user(control, &p->control)) | 952 | if (get_user(control, &p->control)) |
@@ -995,45 +996,41 @@ static int ioctl_queue_iso(struct client *client, void *buffer) | |||
995 | count++; | 996 | count++; |
996 | } | 997 | } |
997 | 998 | ||
998 | request->size -= uptr_to_u64(p) - request->packets; | 999 | a->size -= uptr_to_u64(p) - a->packets; |
999 | request->packets = uptr_to_u64(p); | 1000 | a->packets = uptr_to_u64(p); |
1000 | request->data = client->vm_start + payload; | 1001 | a->data = client->vm_start + payload; |
1001 | 1002 | ||
1002 | return count; | 1003 | return count; |
1003 | } | 1004 | } |
1004 | 1005 | ||
1005 | static int ioctl_start_iso(struct client *client, void *buffer) | 1006 | static int ioctl_start_iso(struct client *client, union ioctl_arg *arg) |
1006 | { | 1007 | { |
1007 | struct fw_cdev_start_iso *request = buffer; | 1008 | struct fw_cdev_start_iso *a = &arg->start_iso; |
1008 | 1009 | ||
1009 | if (client->iso_context == NULL || request->handle != 0) | 1010 | if (client->iso_context == NULL || a->handle != 0) |
1010 | return -EINVAL; | 1011 | return -EINVAL; |
1011 | 1012 | ||
1012 | if (client->iso_context->type == FW_ISO_CONTEXT_RECEIVE) { | 1013 | if (client->iso_context->type == FW_ISO_CONTEXT_RECEIVE && |
1013 | if (request->tags == 0 || request->tags > 15) | 1014 | (a->tags == 0 || a->tags > 15 || a->sync > 15)) |
1014 | return -EINVAL; | 1015 | return -EINVAL; |
1015 | |||
1016 | if (request->sync > 15) | ||
1017 | return -EINVAL; | ||
1018 | } | ||
1019 | 1016 | ||
1020 | return fw_iso_context_start(client->iso_context, request->cycle, | 1017 | return fw_iso_context_start(client->iso_context, |
1021 | request->sync, request->tags); | 1018 | a->cycle, a->sync, a->tags); |
1022 | } | 1019 | } |
1023 | 1020 | ||
1024 | static int ioctl_stop_iso(struct client *client, void *buffer) | 1021 | static int ioctl_stop_iso(struct client *client, union ioctl_arg *arg) |
1025 | { | 1022 | { |
1026 | struct fw_cdev_stop_iso *request = buffer; | 1023 | struct fw_cdev_stop_iso *a = &arg->stop_iso; |
1027 | 1024 | ||
1028 | if (client->iso_context == NULL || request->handle != 0) | 1025 | if (client->iso_context == NULL || a->handle != 0) |
1029 | return -EINVAL; | 1026 | return -EINVAL; |
1030 | 1027 | ||
1031 | return fw_iso_context_stop(client->iso_context); | 1028 | return fw_iso_context_stop(client->iso_context); |
1032 | } | 1029 | } |
1033 | 1030 | ||
1034 | static int ioctl_get_cycle_timer2(struct client *client, void *buffer) | 1031 | static int ioctl_get_cycle_timer2(struct client *client, union ioctl_arg *arg) |
1035 | { | 1032 | { |
1036 | struct fw_cdev_get_cycle_timer2 *request = buffer; | 1033 | struct fw_cdev_get_cycle_timer2 *a = &arg->get_cycle_timer2; |
1037 | struct fw_card *card = client->device->card; | 1034 | struct fw_card *card = client->device->card; |
1038 | struct timespec ts = {0, 0}; | 1035 | struct timespec ts = {0, 0}; |
1039 | u32 cycle_time; | 1036 | u32 cycle_time; |
@@ -1043,7 +1040,7 @@ static int ioctl_get_cycle_timer2(struct client *client, void *buffer) | |||
1043 | 1040 | ||
1044 | cycle_time = card->driver->get_cycle_time(card); | 1041 | cycle_time = card->driver->get_cycle_time(card); |
1045 | 1042 | ||
1046 | switch (request->clk_id) { | 1043 | switch (a->clk_id) { |
1047 | case CLOCK_REALTIME: getnstimeofday(&ts); break; | 1044 | case CLOCK_REALTIME: getnstimeofday(&ts); break; |
1048 | case CLOCK_MONOTONIC: do_posix_clock_monotonic_gettime(&ts); break; | 1045 | case CLOCK_MONOTONIC: do_posix_clock_monotonic_gettime(&ts); break; |
1049 | case CLOCK_MONOTONIC_RAW: getrawmonotonic(&ts); break; | 1046 | case CLOCK_MONOTONIC_RAW: getrawmonotonic(&ts); break; |
@@ -1053,24 +1050,23 @@ static int ioctl_get_cycle_timer2(struct client *client, void *buffer) | |||
1053 | 1050 | ||
1054 | local_irq_enable(); | 1051 | local_irq_enable(); |
1055 | 1052 | ||
1056 | request->tv_sec = ts.tv_sec; | 1053 | a->tv_sec = ts.tv_sec; |
1057 | request->tv_nsec = ts.tv_nsec; | 1054 | a->tv_nsec = ts.tv_nsec; |
1058 | request->cycle_timer = cycle_time; | 1055 | a->cycle_timer = cycle_time; |
1059 | 1056 | ||
1060 | return ret; | 1057 | return ret; |
1061 | } | 1058 | } |
1062 | 1059 | ||
1063 | static int ioctl_get_cycle_timer(struct client *client, void *buffer) | 1060 | static int ioctl_get_cycle_timer(struct client *client, union ioctl_arg *arg) |
1064 | { | 1061 | { |
1065 | struct fw_cdev_get_cycle_timer *request = buffer; | 1062 | struct fw_cdev_get_cycle_timer *a = &arg->get_cycle_timer; |
1066 | struct fw_cdev_get_cycle_timer2 ct2; | 1063 | struct fw_cdev_get_cycle_timer2 ct2; |
1067 | 1064 | ||
1068 | ct2.clk_id = CLOCK_REALTIME; | 1065 | ct2.clk_id = CLOCK_REALTIME; |
1069 | ioctl_get_cycle_timer2(client, &ct2); | 1066 | ioctl_get_cycle_timer2(client, (union ioctl_arg *)&ct2); |
1070 | 1067 | ||
1071 | request->local_time = ct2.tv_sec * USEC_PER_SEC + | 1068 | a->local_time = ct2.tv_sec * USEC_PER_SEC + ct2.tv_nsec / NSEC_PER_USEC; |
1072 | ct2.tv_nsec / NSEC_PER_USEC; | 1069 | a->cycle_timer = ct2.cycle_timer; |
1073 | request->cycle_timer = ct2.cycle_timer; | ||
1074 | 1070 | ||
1075 | return 0; | 1071 | return 0; |
1076 | } | 1072 | } |
@@ -1242,33 +1238,32 @@ static int init_iso_resource(struct client *client, | |||
1242 | return ret; | 1238 | return ret; |
1243 | } | 1239 | } |
1244 | 1240 | ||
1245 | static int ioctl_allocate_iso_resource(struct client *client, void *buffer) | 1241 | static int ioctl_allocate_iso_resource(struct client *client, |
1242 | union ioctl_arg *arg) | ||
1246 | { | 1243 | { |
1247 | struct fw_cdev_allocate_iso_resource *request = buffer; | 1244 | return init_iso_resource(client, |
1248 | 1245 | &arg->allocate_iso_resource, ISO_RES_ALLOC); | |
1249 | return init_iso_resource(client, request, ISO_RES_ALLOC); | ||
1250 | } | 1246 | } |
1251 | 1247 | ||
1252 | static int ioctl_deallocate_iso_resource(struct client *client, void *buffer) | 1248 | static int ioctl_deallocate_iso_resource(struct client *client, |
1249 | union ioctl_arg *arg) | ||
1253 | { | 1250 | { |
1254 | struct fw_cdev_deallocate *request = buffer; | 1251 | return release_client_resource(client, |
1255 | 1252 | arg->deallocate.handle, release_iso_resource, NULL); | |
1256 | return release_client_resource(client, request->handle, | ||
1257 | release_iso_resource, NULL); | ||
1258 | } | 1253 | } |
1259 | 1254 | ||
1260 | static int ioctl_allocate_iso_resource_once(struct client *client, void *buffer) | 1255 | static int ioctl_allocate_iso_resource_once(struct client *client, |
1256 | union ioctl_arg *arg) | ||
1261 | { | 1257 | { |
1262 | struct fw_cdev_allocate_iso_resource *request = buffer; | 1258 | return init_iso_resource(client, |
1263 | 1259 | &arg->allocate_iso_resource, ISO_RES_ALLOC_ONCE); | |
1264 | return init_iso_resource(client, request, ISO_RES_ALLOC_ONCE); | ||
1265 | } | 1260 | } |
1266 | 1261 | ||
1267 | static int ioctl_deallocate_iso_resource_once(struct client *client, void *buffer) | 1262 | static int ioctl_deallocate_iso_resource_once(struct client *client, |
1263 | union ioctl_arg *arg) | ||
1268 | { | 1264 | { |
1269 | struct fw_cdev_allocate_iso_resource *request = buffer; | 1265 | return init_iso_resource(client, |
1270 | 1266 | &arg->allocate_iso_resource, ISO_RES_DEALLOC_ONCE); | |
1271 | return init_iso_resource(client, request, ISO_RES_DEALLOC_ONCE); | ||
1272 | } | 1267 | } |
1273 | 1268 | ||
1274 | /* | 1269 | /* |
@@ -1276,16 +1271,17 @@ static int ioctl_deallocate_iso_resource_once(struct client *client, void *buffe | |||
1276 | * limited by the device's link speed, the local node's link speed, | 1271 | * limited by the device's link speed, the local node's link speed, |
1277 | * and all PHY port speeds between the two links. | 1272 | * and all PHY port speeds between the two links. |
1278 | */ | 1273 | */ |
1279 | static int ioctl_get_speed(struct client *client, void *buffer) | 1274 | static int ioctl_get_speed(struct client *client, union ioctl_arg *arg) |
1280 | { | 1275 | { |
1281 | return client->device->max_speed; | 1276 | return client->device->max_speed; |
1282 | } | 1277 | } |
1283 | 1278 | ||
1284 | static int ioctl_send_broadcast_request(struct client *client, void *buffer) | 1279 | static int ioctl_send_broadcast_request(struct client *client, |
1280 | union ioctl_arg *arg) | ||
1285 | { | 1281 | { |
1286 | struct fw_cdev_send_request *request = buffer; | 1282 | struct fw_cdev_send_request *a = &arg->send_request; |
1287 | 1283 | ||
1288 | switch (request->tcode) { | 1284 | switch (a->tcode) { |
1289 | case TCODE_WRITE_QUADLET_REQUEST: | 1285 | case TCODE_WRITE_QUADLET_REQUEST: |
1290 | case TCODE_WRITE_BLOCK_REQUEST: | 1286 | case TCODE_WRITE_BLOCK_REQUEST: |
1291 | break; | 1287 | break; |
@@ -1294,36 +1290,36 @@ static int ioctl_send_broadcast_request(struct client *client, void *buffer) | |||
1294 | } | 1290 | } |
1295 | 1291 | ||
1296 | /* Security policy: Only allow accesses to Units Space. */ | 1292 | /* Security policy: Only allow accesses to Units Space. */ |
1297 | if (request->offset < CSR_REGISTER_BASE + CSR_CONFIG_ROM_END) | 1293 | if (a->offset < CSR_REGISTER_BASE + CSR_CONFIG_ROM_END) |
1298 | return -EACCES; | 1294 | return -EACCES; |
1299 | 1295 | ||
1300 | return init_request(client, request, LOCAL_BUS | 0x3f, SCODE_100); | 1296 | return init_request(client, a, LOCAL_BUS | 0x3f, SCODE_100); |
1301 | } | 1297 | } |
1302 | 1298 | ||
1303 | static int ioctl_send_stream_packet(struct client *client, void *buffer) | 1299 | static int ioctl_send_stream_packet(struct client *client, union ioctl_arg *arg) |
1304 | { | 1300 | { |
1305 | struct fw_cdev_send_stream_packet *p = buffer; | 1301 | struct fw_cdev_send_stream_packet *a = &arg->send_stream_packet; |
1306 | struct fw_cdev_send_request request; | 1302 | struct fw_cdev_send_request request; |
1307 | int dest; | 1303 | int dest; |
1308 | 1304 | ||
1309 | if (p->speed > client->device->card->link_speed || | 1305 | if (a->speed > client->device->card->link_speed || |
1310 | p->length > 1024 << p->speed) | 1306 | a->length > 1024 << a->speed) |
1311 | return -EIO; | 1307 | return -EIO; |
1312 | 1308 | ||
1313 | if (p->tag > 3 || p->channel > 63 || p->sy > 15) | 1309 | if (a->tag > 3 || a->channel > 63 || a->sy > 15) |
1314 | return -EINVAL; | 1310 | return -EINVAL; |
1315 | 1311 | ||
1316 | dest = fw_stream_packet_destination_id(p->tag, p->channel, p->sy); | 1312 | dest = fw_stream_packet_destination_id(a->tag, a->channel, a->sy); |
1317 | request.tcode = TCODE_STREAM_DATA; | 1313 | request.tcode = TCODE_STREAM_DATA; |
1318 | request.length = p->length; | 1314 | request.length = a->length; |
1319 | request.closure = p->closure; | 1315 | request.closure = a->closure; |
1320 | request.data = p->data; | 1316 | request.data = a->data; |
1321 | request.generation = p->generation; | 1317 | request.generation = a->generation; |
1322 | 1318 | ||
1323 | return init_request(client, &request, dest, p->speed); | 1319 | return init_request(client, &request, dest, a->speed); |
1324 | } | 1320 | } |
1325 | 1321 | ||
1326 | static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { | 1322 | static int (* const ioctl_handlers[])(struct client *, union ioctl_arg *) = { |
1327 | ioctl_get_info, | 1323 | ioctl_get_info, |
1328 | ioctl_send_request, | 1324 | ioctl_send_request, |
1329 | ioctl_allocate, | 1325 | ioctl_allocate, |
@@ -1350,24 +1346,7 @@ static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { | |||
1350 | static int dispatch_ioctl(struct client *client, | 1346 | static int dispatch_ioctl(struct client *client, |
1351 | unsigned int cmd, void __user *arg) | 1347 | unsigned int cmd, void __user *arg) |
1352 | { | 1348 | { |
1353 | char buffer[sizeof(union { | 1349 | union ioctl_arg buffer; |
1354 | struct fw_cdev_get_info _00; | ||
1355 | struct fw_cdev_send_request _01; | ||
1356 | struct fw_cdev_allocate _02; | ||
1357 | struct fw_cdev_deallocate _03; | ||
1358 | struct fw_cdev_send_response _04; | ||
1359 | struct fw_cdev_initiate_bus_reset _05; | ||
1360 | struct fw_cdev_add_descriptor _06; | ||
1361 | struct fw_cdev_remove_descriptor _07; | ||
1362 | struct fw_cdev_create_iso_context _08; | ||
1363 | struct fw_cdev_queue_iso _09; | ||
1364 | struct fw_cdev_start_iso _0a; | ||
1365 | struct fw_cdev_stop_iso _0b; | ||
1366 | struct fw_cdev_get_cycle_timer _0c; | ||
1367 | struct fw_cdev_allocate_iso_resource _0d; | ||
1368 | struct fw_cdev_send_stream_packet _13; | ||
1369 | struct fw_cdev_get_cycle_timer2 _14; | ||
1370 | })]; | ||
1371 | int ret; | 1350 | int ret; |
1372 | 1351 | ||
1373 | if (_IOC_TYPE(cmd) != '#' || | 1352 | if (_IOC_TYPE(cmd) != '#' || |
@@ -1376,17 +1355,17 @@ static int dispatch_ioctl(struct client *client, | |||
1376 | 1355 | ||
1377 | if (_IOC_DIR(cmd) & _IOC_WRITE) { | 1356 | if (_IOC_DIR(cmd) & _IOC_WRITE) { |
1378 | if (_IOC_SIZE(cmd) > sizeof(buffer) || | 1357 | if (_IOC_SIZE(cmd) > sizeof(buffer) || |
1379 | copy_from_user(buffer, arg, _IOC_SIZE(cmd))) | 1358 | copy_from_user(&buffer, arg, _IOC_SIZE(cmd))) |
1380 | return -EFAULT; | 1359 | return -EFAULT; |
1381 | } | 1360 | } |
1382 | 1361 | ||
1383 | ret = ioctl_handlers[_IOC_NR(cmd)](client, buffer); | 1362 | ret = ioctl_handlers[_IOC_NR(cmd)](client, &buffer); |
1384 | if (ret < 0) | 1363 | if (ret < 0) |
1385 | return ret; | 1364 | return ret; |
1386 | 1365 | ||
1387 | if (_IOC_DIR(cmd) & _IOC_READ) { | 1366 | if (_IOC_DIR(cmd) & _IOC_READ) { |
1388 | if (_IOC_SIZE(cmd) > sizeof(buffer) || | 1367 | if (_IOC_SIZE(cmd) > sizeof(buffer) || |
1389 | copy_to_user(arg, buffer, _IOC_SIZE(cmd))) | 1368 | copy_to_user(arg, &buffer, _IOC_SIZE(cmd))) |
1390 | return -EFAULT; | 1369 | return -EFAULT; |
1391 | } | 1370 | } |
1392 | 1371 | ||