aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/uvc
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@skynet.be>2008-07-03 23:36:21 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-07-20 06:17:45 -0400
commite01117c81676dc9897f567e32cdc13a26e85280b (patch)
tree371bc23453782045f5236daaf891110b0337f013 /drivers/media/video/uvc
parent291358785cde5536d98a4f3cae77efd8ca626486 (diff)
V4L/DVB (8209): uvcvideo: Don't free URB buffers on suspend.
All submitted URBs must be killed at suspend time, but URB buffers don't have to be freed. Avoiding a free on suspend/reallocate on resume lowers the presure on system memory. Signed-off-by: Laurent Pinchart <laurent.pinchart@skynet.be> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/uvc')
-rw-r--r--drivers/media/video/uvc/uvc_video.c96
-rw-r--r--drivers/media/video/uvc/uvcvideo.h2
2 files changed, 66 insertions, 32 deletions
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c
index 8eb5748c446e..817af2e36362 100644
--- a/drivers/media/video/uvc/uvc_video.c
+++ b/drivers/media/video/uvc/uvc_video.c
@@ -554,9 +554,56 @@ static void uvc_video_complete(struct urb *urb)
554} 554}
555 555
556/* 556/*
557 * Free transfer buffers.
558 */
559static void uvc_free_urb_buffers(struct uvc_video_device *video)
560{
561 unsigned int i;
562
563 for (i = 0; i < UVC_URBS; ++i) {
564 if (video->urb_buffer[i]) {
565 usb_buffer_free(video->dev->udev, video->urb_size,
566 video->urb_buffer[i], video->urb_dma[i]);
567 video->urb_buffer[i] = NULL;
568 }
569 }
570
571 video->urb_size = 0;
572}
573
574/*
575 * Allocate transfer buffers. This function can be called with buffers
576 * already allocated when resuming from suspend, in which case it will
577 * return without touching the buffers.
578 *
579 * Return 0 on success or -ENOMEM when out of memory.
580 */
581static int uvc_alloc_urb_buffers(struct uvc_video_device *video,
582 unsigned int size)
583{
584 unsigned int i;
585
586 /* Buffers are already allocated, bail out. */
587 if (video->urb_size)
588 return 0;
589
590 for (i = 0; i < UVC_URBS; ++i) {
591 video->urb_buffer[i] = usb_buffer_alloc(video->dev->udev,
592 size, GFP_KERNEL, &video->urb_dma[i]);
593 if (video->urb_buffer[i] == NULL) {
594 uvc_free_urb_buffers(video);
595 return -ENOMEM;
596 }
597 }
598
599 video->urb_size = size;
600 return 0;
601}
602
603/*
557 * Uninitialize isochronous/bulk URBs and free transfer buffers. 604 * Uninitialize isochronous/bulk URBs and free transfer buffers.
558 */ 605 */
559static void uvc_uninit_video(struct uvc_video_device *video) 606static void uvc_uninit_video(struct uvc_video_device *video, int free_buffers)
560{ 607{
561 struct urb *urb; 608 struct urb *urb;
562 unsigned int i; 609 unsigned int i;
@@ -566,19 +613,12 @@ static void uvc_uninit_video(struct uvc_video_device *video)
566 continue; 613 continue;
567 614
568 usb_kill_urb(urb); 615 usb_kill_urb(urb);
569 /* urb->transfer_buffer_length is not touched by USB core, so
570 * we can use it here as the buffer length.
571 */
572 if (video->urb_buffer[i]) {
573 usb_buffer_free(video->dev->udev,
574 urb->transfer_buffer_length,
575 video->urb_buffer[i], urb->transfer_dma);
576 video->urb_buffer[i] = NULL;
577 }
578
579 usb_free_urb(urb); 616 usb_free_urb(urb);
580 video->urb[i] = NULL; 617 video->urb[i] = NULL;
581 } 618 }
619
620 if (free_buffers)
621 uvc_free_urb_buffers(video);
582} 622}
583 623
584/* 624/*
@@ -610,18 +650,13 @@ static int uvc_init_video_isoc(struct uvc_video_device *video,
610 650
611 size = npackets * psize; 651 size = npackets * psize;
612 652
653 if (uvc_alloc_urb_buffers(video, size) < 0)
654 return -ENOMEM;
655
613 for (i = 0; i < UVC_URBS; ++i) { 656 for (i = 0; i < UVC_URBS; ++i) {
614 urb = usb_alloc_urb(npackets, gfp_flags); 657 urb = usb_alloc_urb(npackets, gfp_flags);
615 if (urb == NULL) { 658 if (urb == NULL) {
616 uvc_uninit_video(video); 659 uvc_uninit_video(video, 1);
617 return -ENOMEM;
618 }
619
620 video->urb_buffer[i] = usb_buffer_alloc(video->dev->udev,
621 size, gfp_flags, &urb->transfer_dma);
622 if (video->urb_buffer[i] == NULL) {
623 usb_free_urb(urb);
624 uvc_uninit_video(video);
625 return -ENOMEM; 660 return -ENOMEM;
626 } 661 }
627 662
@@ -632,6 +667,7 @@ static int uvc_init_video_isoc(struct uvc_video_device *video,
632 urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; 667 urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
633 urb->interval = ep->desc.bInterval; 668 urb->interval = ep->desc.bInterval;
634 urb->transfer_buffer = video->urb_buffer[i]; 669 urb->transfer_buffer = video->urb_buffer[i];
670 urb->transfer_dma = video->urb_dma[i];
635 urb->complete = uvc_video_complete; 671 urb->complete = uvc_video_complete;
636 urb->number_of_packets = npackets; 672 urb->number_of_packets = npackets;
637 urb->transfer_buffer_length = size; 673 urb->transfer_buffer_length = size;
@@ -671,20 +707,15 @@ static int uvc_init_video_bulk(struct uvc_video_device *video,
671 if (size > psize * UVC_MAX_ISO_PACKETS) 707 if (size > psize * UVC_MAX_ISO_PACKETS)
672 size = psize * UVC_MAX_ISO_PACKETS; 708 size = psize * UVC_MAX_ISO_PACKETS;
673 709
710 if (uvc_alloc_urb_buffers(video, size) < 0)
711 return -ENOMEM;
712
674 pipe = usb_rcvbulkpipe(video->dev->udev, ep->desc.bEndpointAddress); 713 pipe = usb_rcvbulkpipe(video->dev->udev, ep->desc.bEndpointAddress);
675 714
676 for (i = 0; i < UVC_URBS; ++i) { 715 for (i = 0; i < UVC_URBS; ++i) {
677 urb = usb_alloc_urb(0, gfp_flags); 716 urb = usb_alloc_urb(0, gfp_flags);
678 if (urb == NULL) { 717 if (urb == NULL) {
679 uvc_uninit_video(video); 718 uvc_uninit_video(video, 1);
680 return -ENOMEM;
681 }
682
683 video->urb_buffer[i] = usb_buffer_alloc(video->dev->udev,
684 size, gfp_flags, &urb->transfer_dma);
685 if (video->urb_buffer[i] == NULL) {
686 usb_free_urb(urb);
687 uvc_uninit_video(video);
688 return -ENOMEM; 719 return -ENOMEM;
689 } 720 }
690 721
@@ -692,6 +723,7 @@ static int uvc_init_video_bulk(struct uvc_video_device *video,
692 video->urb_buffer[i], size, uvc_video_complete, 723 video->urb_buffer[i], size, uvc_video_complete,
693 video); 724 video);
694 urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; 725 urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
726 urb->transfer_dma = video->urb_dma[i];
695 727
696 video->urb[i] = urb; 728 video->urb[i] = urb;
697 } 729 }
@@ -766,7 +798,7 @@ static int uvc_init_video(struct uvc_video_device *video, gfp_t gfp_flags)
766 if ((ret = usb_submit_urb(video->urb[i], gfp_flags)) < 0) { 798 if ((ret = usb_submit_urb(video->urb[i], gfp_flags)) < 0) {
767 uvc_printk(KERN_ERR, "Failed to submit URB %u " 799 uvc_printk(KERN_ERR, "Failed to submit URB %u "
768 "(%d).\n", i, ret); 800 "(%d).\n", i, ret);
769 uvc_uninit_video(video); 801 uvc_uninit_video(video, 1);
770 return ret; 802 return ret;
771 } 803 }
772 } 804 }
@@ -791,7 +823,7 @@ int uvc_video_suspend(struct uvc_video_device *video)
791 return 0; 823 return 0;
792 824
793 video->frozen = 1; 825 video->frozen = 1;
794 uvc_uninit_video(video); 826 uvc_uninit_video(video, 0);
795 usb_set_interface(video->dev->udev, video->streaming->intfnum, 0); 827 usb_set_interface(video->dev->udev, video->streaming->intfnum, 0);
796 return 0; 828 return 0;
797} 829}
@@ -920,7 +952,7 @@ int uvc_video_enable(struct uvc_video_device *video, int enable)
920 int ret; 952 int ret;
921 953
922 if (!enable) { 954 if (!enable) {
923 uvc_uninit_video(video); 955 uvc_uninit_video(video, 1);
924 usb_set_interface(video->dev->udev, 956 usb_set_interface(video->dev->udev,
925 video->streaming->intfnum, 0); 957 video->streaming->intfnum, 0);
926 uvc_queue_enable(&video->queue, 0); 958 uvc_queue_enable(&video->queue, 0);
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h
index a995a780db1c..2444b8a9d2a0 100644
--- a/drivers/media/video/uvc/uvcvideo.h
+++ b/drivers/media/video/uvc/uvcvideo.h
@@ -602,6 +602,8 @@ struct uvc_video_device {
602 602
603 struct urb *urb[UVC_URBS]; 603 struct urb *urb[UVC_URBS];
604 char *urb_buffer[UVC_URBS]; 604 char *urb_buffer[UVC_URBS];
605 dma_addr_t urb_dma[UVC_URBS];
606 unsigned int urb_size;
605 607
606 __u8 last_fid; 608 __u8 last_fid;
607}; 609};