aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/firewire/core-cdev.c325
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
371static int ioctl_get_info(struct client *client, void *buffer) 371union 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
390static 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
574static int ioctl_send_request(struct client *client, void *buffer) 591static 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
686static int ioctl_allocate(struct client *client, void *buffer) 701static 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, &region); 720 ret = fw_core_add_address_handler(&r->handler, &region);
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
722static int ioctl_deallocate(struct client *client, void *buffer) 737static 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
730static int ioctl_send_response(struct client *client, void *buffer) 743static 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
760static int ioctl_initiate_bus_reset(struct client *client, void *buffer) 773static 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
770static void release_descriptor(struct client *client, 779static 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
780static int ioctl_add_descriptor(struct client *client, void *buffer) 789static 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
827static int ioctl_remove_descriptor(struct client *client, void *buffer) 835static 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
854static int ioctl_create_iso_context(struct client *client, void *buffer) 860static 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
909static int ioctl_queue_iso(struct client *client, void *buffer) 910static 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
1005static int ioctl_start_iso(struct client *client, void *buffer) 1006static 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
1024static int ioctl_stop_iso(struct client *client, void *buffer) 1021static 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
1034static int ioctl_get_cycle_timer2(struct client *client, void *buffer) 1031static 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
1063static int ioctl_get_cycle_timer(struct client *client, void *buffer) 1060static 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
1245static int ioctl_allocate_iso_resource(struct client *client, void *buffer) 1241static 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
1252static int ioctl_deallocate_iso_resource(struct client *client, void *buffer) 1248static 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
1260static int ioctl_allocate_iso_resource_once(struct client *client, void *buffer) 1255static 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
1267static int ioctl_deallocate_iso_resource_once(struct client *client, void *buffer) 1262static 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 */
1279static int ioctl_get_speed(struct client *client, void *buffer) 1274static 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
1284static int ioctl_send_broadcast_request(struct client *client, void *buffer) 1279static 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
1303static int ioctl_send_stream_packet(struct client *client, void *buffer) 1299static 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
1326static int (* const ioctl_handlers[])(struct client *client, void *buffer) = { 1322static 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) = {
1350static int dispatch_ioctl(struct client *client, 1346static 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