aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/firewire/fw-device-cdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firewire/fw-device-cdev.c')
-rw-r--r--drivers/firewire/fw-device-cdev.c278
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
261static int ioctl_get_info(struct client *client, void __user *arg) 261static 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
372static ssize_t ioctl_send_request(struct client *client, void __user *arg) 366static 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
498static int ioctl_allocate(struct client *client, void __user *arg) 489static 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, &region) < 0) { 507 if (fw_core_add_address_handler(&handler->handler, &region) < 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
534static int ioctl_deallocate(struct client *client, void __user *arg) 519static 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
544static int ioctl_send_response(struct client *client, void __user *arg) 526static 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
566static int ioctl_initiate_bus_reset(struct client *client, void __user *arg) 546static 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
595static int ioctl_add_descriptor(struct client *client, void __user *arg) 572static 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
639static int ioctl_remove_descriptor(struct client *client, void __user *arg) 610static 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
649static void 617static 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
670static int ioctl_create_iso_context(struct client *client, void __user *arg) 638static 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
709static int ioctl_queue_iso(struct client *client, void __user *arg) 674static 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
798static int ioctl_start_iso(struct client *client, void __user *arg) 758static 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
817static int ioctl_stop_iso(struct client *client, void __user *arg) 774static 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
779static 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
822static int 794static int
823dispatch_ioctl(struct client *client, unsigned int cmd, void __user *arg) 795dispatch_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
855static long 823static long