diff options
Diffstat (limited to 'drivers/media/usb/tm6000/tm6000-video.c')
-rw-r--r-- | drivers/media/usb/tm6000/tm6000-video.c | 112 |
1 files changed, 93 insertions, 19 deletions
diff --git a/drivers/media/usb/tm6000/tm6000-video.c b/drivers/media/usb/tm6000/tm6000-video.c index f656fd7a39a2..82968017a253 100644 --- a/drivers/media/usb/tm6000/tm6000-video.c +++ b/drivers/media/usb/tm6000/tm6000-video.c | |||
@@ -49,12 +49,15 @@ | |||
49 | #define TM6000_MIN_BUF 4 | 49 | #define TM6000_MIN_BUF 4 |
50 | #define TM6000_DEF_BUF 8 | 50 | #define TM6000_DEF_BUF 8 |
51 | 51 | ||
52 | #define TM6000_NUM_URB_BUF 8 | ||
53 | |||
52 | #define TM6000_MAX_ISO_PACKETS 46 /* Max number of ISO packets */ | 54 | #define TM6000_MAX_ISO_PACKETS 46 /* Max number of ISO packets */ |
53 | 55 | ||
54 | /* Declare static vars that will be used as parameters */ | 56 | /* Declare static vars that will be used as parameters */ |
55 | static unsigned int vid_limit = 16; /* Video memory limit, in Mb */ | 57 | static unsigned int vid_limit = 16; /* Video memory limit, in Mb */ |
56 | static int video_nr = -1; /* /dev/videoN, -1 for autodetect */ | 58 | static int video_nr = -1; /* /dev/videoN, -1 for autodetect */ |
57 | static int radio_nr = -1; /* /dev/radioN, -1 for autodetect */ | 59 | static int radio_nr = -1; /* /dev/radioN, -1 for autodetect */ |
60 | static int keep_urb; /* keep urb buffers allocated */ | ||
58 | 61 | ||
59 | /* Debug level */ | 62 | /* Debug level */ |
60 | int tm6000_debug; | 63 | int tm6000_debug; |
@@ -538,6 +541,71 @@ static void tm6000_irq_callback(struct urb *urb) | |||
538 | } | 541 | } |
539 | 542 | ||
540 | /* | 543 | /* |
544 | * Allocate URB buffers | ||
545 | */ | ||
546 | static int tm6000_alloc_urb_buffers(struct tm6000_core *dev) | ||
547 | { | ||
548 | int num_bufs = TM6000_NUM_URB_BUF; | ||
549 | int i; | ||
550 | |||
551 | if (dev->urb_buffer != NULL) | ||
552 | return 0; | ||
553 | |||
554 | dev->urb_buffer = kmalloc(sizeof(void *)*num_bufs, GFP_KERNEL); | ||
555 | if (!dev->urb_buffer) { | ||
556 | tm6000_err("cannot allocate memory for urb buffers\n"); | ||
557 | return -ENOMEM; | ||
558 | } | ||
559 | |||
560 | dev->urb_dma = kmalloc(sizeof(dma_addr_t *)*num_bufs, GFP_KERNEL); | ||
561 | if (!dev->urb_dma) { | ||
562 | tm6000_err("cannot allocate memory for urb dma pointers\n"); | ||
563 | return -ENOMEM; | ||
564 | } | ||
565 | |||
566 | for (i = 0; i < num_bufs; i++) { | ||
567 | dev->urb_buffer[i] = usb_alloc_coherent( | ||
568 | dev->udev, dev->urb_size, | ||
569 | GFP_KERNEL, &dev->urb_dma[i]); | ||
570 | if (!dev->urb_buffer[i]) { | ||
571 | tm6000_err("unable to allocate %i bytes for transfer buffer %i\n", | ||
572 | dev->urb_size, i); | ||
573 | return -ENOMEM; | ||
574 | } | ||
575 | memset(dev->urb_buffer[i], 0, dev->urb_size); | ||
576 | } | ||
577 | |||
578 | return 0; | ||
579 | } | ||
580 | |||
581 | /* | ||
582 | * Free URB buffers | ||
583 | */ | ||
584 | static int tm6000_free_urb_buffers(struct tm6000_core *dev) | ||
585 | { | ||
586 | int i; | ||
587 | |||
588 | if (dev->urb_buffer == NULL) | ||
589 | return 0; | ||
590 | |||
591 | for (i = 0; i < TM6000_NUM_URB_BUF; i++) { | ||
592 | if (dev->urb_buffer[i]) { | ||
593 | usb_free_coherent(dev->udev, | ||
594 | dev->urb_size, | ||
595 | dev->urb_buffer[i], | ||
596 | dev->urb_dma[i]); | ||
597 | dev->urb_buffer[i] = NULL; | ||
598 | } | ||
599 | } | ||
600 | kfree(dev->urb_buffer); | ||
601 | kfree(dev->urb_dma); | ||
602 | dev->urb_buffer = NULL; | ||
603 | dev->urb_dma = NULL; | ||
604 | |||
605 | return 0; | ||
606 | } | ||
607 | |||
608 | /* | ||
541 | * Stop and Deallocate URBs | 609 | * Stop and Deallocate URBs |
542 | */ | 610 | */ |
543 | static void tm6000_uninit_isoc(struct tm6000_core *dev) | 611 | static void tm6000_uninit_isoc(struct tm6000_core *dev) |
@@ -551,18 +619,15 @@ static void tm6000_uninit_isoc(struct tm6000_core *dev) | |||
551 | if (urb) { | 619 | if (urb) { |
552 | usb_kill_urb(urb); | 620 | usb_kill_urb(urb); |
553 | usb_unlink_urb(urb); | 621 | usb_unlink_urb(urb); |
554 | if (dev->isoc_ctl.transfer_buffer[i]) { | ||
555 | usb_free_coherent(dev->udev, | ||
556 | urb->transfer_buffer_length, | ||
557 | dev->isoc_ctl.transfer_buffer[i], | ||
558 | urb->transfer_dma); | ||
559 | } | ||
560 | usb_free_urb(urb); | 622 | usb_free_urb(urb); |
561 | dev->isoc_ctl.urb[i] = NULL; | 623 | dev->isoc_ctl.urb[i] = NULL; |
562 | } | 624 | } |
563 | dev->isoc_ctl.transfer_buffer[i] = NULL; | 625 | dev->isoc_ctl.transfer_buffer[i] = NULL; |
564 | } | 626 | } |
565 | 627 | ||
628 | if (!keep_urb) | ||
629 | tm6000_free_urb_buffers(dev); | ||
630 | |||
566 | kfree(dev->isoc_ctl.urb); | 631 | kfree(dev->isoc_ctl.urb); |
567 | kfree(dev->isoc_ctl.transfer_buffer); | 632 | kfree(dev->isoc_ctl.transfer_buffer); |
568 | 633 | ||
@@ -572,12 +637,13 @@ static void tm6000_uninit_isoc(struct tm6000_core *dev) | |||
572 | } | 637 | } |
573 | 638 | ||
574 | /* | 639 | /* |
575 | * Allocate URBs and start IRQ | 640 | * Assign URBs and start IRQ |
576 | */ | 641 | */ |
577 | static int tm6000_prepare_isoc(struct tm6000_core *dev) | 642 | static int tm6000_prepare_isoc(struct tm6000_core *dev) |
578 | { | 643 | { |
579 | struct tm6000_dmaqueue *dma_q = &dev->vidq; | 644 | struct tm6000_dmaqueue *dma_q = &dev->vidq; |
580 | int i, j, sb_size, pipe, size, max_packets, num_bufs = 8; | 645 | int i, j, sb_size, pipe, size, max_packets; |
646 | int num_bufs = TM6000_NUM_URB_BUF; | ||
581 | struct urb *urb; | 647 | struct urb *urb; |
582 | 648 | ||
583 | /* De-allocates all pending stuff */ | 649 | /* De-allocates all pending stuff */ |
@@ -605,6 +671,7 @@ static int tm6000_prepare_isoc(struct tm6000_core *dev) | |||
605 | 671 | ||
606 | max_packets = TM6000_MAX_ISO_PACKETS; | 672 | max_packets = TM6000_MAX_ISO_PACKETS; |
607 | sb_size = max_packets * size; | 673 | sb_size = max_packets * size; |
674 | dev->urb_size = sb_size; | ||
608 | 675 | ||
609 | dev->isoc_ctl.num_bufs = num_bufs; | 676 | dev->isoc_ctl.num_bufs = num_bufs; |
610 | 677 | ||
@@ -627,6 +694,17 @@ static int tm6000_prepare_isoc(struct tm6000_core *dev) | |||
627 | max_packets, num_bufs, sb_size, | 694 | max_packets, num_bufs, sb_size, |
628 | dev->isoc_in.maxsize, size); | 695 | dev->isoc_in.maxsize, size); |
629 | 696 | ||
697 | |||
698 | if (!dev->urb_buffer && tm6000_alloc_urb_buffers(dev) < 0) { | ||
699 | tm6000_err("cannot allocate memory for urb buffers\n"); | ||
700 | |||
701 | /* call free, as some buffers might have been allocated */ | ||
702 | tm6000_free_urb_buffers(dev); | ||
703 | kfree(dev->isoc_ctl.urb); | ||
704 | kfree(dev->isoc_ctl.transfer_buffer); | ||
705 | return -ENOMEM; | ||
706 | } | ||
707 | |||
630 | /* allocate urbs and transfer buffers */ | 708 | /* allocate urbs and transfer buffers */ |
631 | for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { | 709 | for (i = 0; i < dev->isoc_ctl.num_bufs; i++) { |
632 | urb = usb_alloc_urb(max_packets, GFP_KERNEL); | 710 | urb = usb_alloc_urb(max_packets, GFP_KERNEL); |
@@ -638,17 +716,8 @@ static int tm6000_prepare_isoc(struct tm6000_core *dev) | |||
638 | } | 716 | } |
639 | dev->isoc_ctl.urb[i] = urb; | 717 | dev->isoc_ctl.urb[i] = urb; |
640 | 718 | ||
641 | dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->udev, | 719 | urb->transfer_dma = dev->urb_dma[i]; |
642 | sb_size, GFP_KERNEL, &urb->transfer_dma); | 720 | dev->isoc_ctl.transfer_buffer[i] = dev->urb_buffer[i]; |
643 | if (!dev->isoc_ctl.transfer_buffer[i]) { | ||
644 | tm6000_err("unable to allocate %i bytes for transfer" | ||
645 | " buffer %i%s\n", | ||
646 | sb_size, i, | ||
647 | in_interrupt() ? " while in int" : ""); | ||
648 | tm6000_uninit_isoc(dev); | ||
649 | return -ENOMEM; | ||
650 | } | ||
651 | memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size); | ||
652 | 721 | ||
653 | usb_fill_bulk_urb(urb, dev->udev, pipe, | 722 | usb_fill_bulk_urb(urb, dev->udev, pipe, |
654 | dev->isoc_ctl.transfer_buffer[i], sb_size, | 723 | dev->isoc_ctl.transfer_buffer[i], sb_size, |
@@ -1826,6 +1895,9 @@ int tm6000_v4l2_unregister(struct tm6000_core *dev) | |||
1826 | { | 1895 | { |
1827 | video_unregister_device(dev->vfd); | 1896 | video_unregister_device(dev->vfd); |
1828 | 1897 | ||
1898 | /* if URB buffers are still allocated free them now */ | ||
1899 | tm6000_free_urb_buffers(dev); | ||
1900 | |||
1829 | if (dev->radio_dev) { | 1901 | if (dev->radio_dev) { |
1830 | if (video_is_registered(dev->radio_dev)) | 1902 | if (video_is_registered(dev->radio_dev)) |
1831 | video_unregister_device(dev->radio_dev); | 1903 | video_unregister_device(dev->radio_dev); |
@@ -1851,3 +1923,5 @@ MODULE_PARM_DESC(debug, "activates debug info"); | |||
1851 | module_param(vid_limit, int, 0644); | 1923 | module_param(vid_limit, int, 0644); |
1852 | MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes"); | 1924 | MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes"); |
1853 | 1925 | ||
1926 | module_param(keep_urb, bool, 0); | ||
1927 | MODULE_PARM_DESC(keep_urb, "Keep urb buffers allocated even when the device is closed by the user"); | ||