diff options
author | Laurent Pinchart <laurent.pinchart@skynet.be> | 2009-01-18 15:46:30 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-03-30 11:42:26 -0400 |
commit | efdc8a9585ce02e70e538e46f235aefd63a3f8da (patch) | |
tree | af233b7335af3914211348d83da4e32c8459be19 /drivers/media/video/uvc | |
parent | f61d1d8a563b1f3c5f1f55d856278aae3fd3987e (diff) |
V4L/DVB (10295): uvcvideo: Retry URB buffers allocation when the system is low on memory.
URB buffers for video transfers are sized to UVC_MAX_PACKETS bulk/isochronous
packets by default. If the system is too low on memory try successively
smaller numbers of packets until allocation succeeds.
Tested-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Laurent Pinchart <laurent.pinchart@skynet.be>
Reviewed-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/uvc')
-rw-r--r-- | drivers/media/video/uvc/uvc_video.c | 79 | ||||
-rw-r--r-- | drivers/media/video/uvc/uvcvideo.h | 6 |
2 files changed, 44 insertions, 41 deletions
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index 9bc4705be78d..7ebb89539c36 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c | |||
@@ -699,27 +699,47 @@ static void uvc_free_urb_buffers(struct uvc_video_device *video) | |||
699 | * already allocated when resuming from suspend, in which case it will | 699 | * already allocated when resuming from suspend, in which case it will |
700 | * return without touching the buffers. | 700 | * return without touching the buffers. |
701 | * | 701 | * |
702 | * Return 0 on success or -ENOMEM when out of memory. | 702 | * Limit the buffer size to UVC_MAX_PACKETS bulk/isochronous packets. If the |
703 | * system is too low on memory try successively smaller numbers of packets | ||
704 | * until allocation succeeds. | ||
705 | * | ||
706 | * Return the number of allocated packets on success or 0 when out of memory. | ||
703 | */ | 707 | */ |
704 | static int uvc_alloc_urb_buffers(struct uvc_video_device *video, | 708 | static int uvc_alloc_urb_buffers(struct uvc_video_device *video, |
705 | unsigned int size) | 709 | unsigned int size, unsigned int psize, gfp_t gfp_flags) |
706 | { | 710 | { |
711 | unsigned int npackets; | ||
707 | unsigned int i; | 712 | unsigned int i; |
708 | 713 | ||
709 | /* Buffers are already allocated, bail out. */ | 714 | /* Buffers are already allocated, bail out. */ |
710 | if (video->urb_size) | 715 | if (video->urb_size) |
711 | return 0; | 716 | return 0; |
712 | 717 | ||
713 | for (i = 0; i < UVC_URBS; ++i) { | 718 | /* Compute the number of packets. Bulk endpoints might transfer UVC |
714 | video->urb_buffer[i] = usb_buffer_alloc(video->dev->udev, | 719 | * payloads accross multiple URBs. |
715 | size, GFP_KERNEL, &video->urb_dma[i]); | 720 | */ |
716 | if (video->urb_buffer[i] == NULL) { | 721 | npackets = DIV_ROUND_UP(size, psize); |
717 | uvc_free_urb_buffers(video); | 722 | if (npackets > UVC_MAX_PACKETS) |
718 | return -ENOMEM; | 723 | npackets = UVC_MAX_PACKETS; |
724 | |||
725 | /* Retry allocations until one succeed. */ | ||
726 | for (; npackets > 1; npackets /= 2) { | ||
727 | for (i = 0; i < UVC_URBS; ++i) { | ||
728 | video->urb_buffer[i] = usb_buffer_alloc( | ||
729 | video->dev->udev, psize * npackets, | ||
730 | gfp_flags | __GFP_NOWARN, &video->urb_dma[i]); | ||
731 | if (!video->urb_buffer[i]) { | ||
732 | uvc_free_urb_buffers(video); | ||
733 | break; | ||
734 | } | ||
735 | } | ||
736 | |||
737 | if (i == UVC_URBS) { | ||
738 | video->urb_size = psize * npackets; | ||
739 | return npackets; | ||
719 | } | 740 | } |
720 | } | 741 | } |
721 | 742 | ||
722 | video->urb_size = size; | ||
723 | return 0; | 743 | return 0; |
724 | } | 744 | } |
725 | 745 | ||
@@ -753,29 +773,19 @@ static int uvc_init_video_isoc(struct uvc_video_device *video, | |||
753 | { | 773 | { |
754 | struct urb *urb; | 774 | struct urb *urb; |
755 | unsigned int npackets, i, j; | 775 | unsigned int npackets, i, j; |
756 | __u16 psize; | 776 | u16 psize; |
757 | __u32 size; | 777 | u32 size; |
758 | 778 | ||
759 | /* Compute the number of isochronous packets to allocate by dividing | ||
760 | * the maximum video frame size by the packet size. Limit the result | ||
761 | * to UVC_MAX_ISO_PACKETS. | ||
762 | */ | ||
763 | psize = le16_to_cpu(ep->desc.wMaxPacketSize); | 779 | psize = le16_to_cpu(ep->desc.wMaxPacketSize); |
764 | psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); | 780 | psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); |
765 | |||
766 | size = video->streaming->ctrl.dwMaxVideoFrameSize; | 781 | size = video->streaming->ctrl.dwMaxVideoFrameSize; |
767 | if (size > UVC_MAX_FRAME_SIZE) | ||
768 | return -EINVAL; | ||
769 | 782 | ||
770 | npackets = DIV_ROUND_UP(size, psize); | 783 | npackets = uvc_alloc_urb_buffers(video, size, psize, gfp_flags); |
771 | if (npackets > UVC_MAX_ISO_PACKETS) | 784 | if (npackets == 0) |
772 | npackets = UVC_MAX_ISO_PACKETS; | 785 | return -ENOMEM; |
773 | 786 | ||
774 | size = npackets * psize; | 787 | size = npackets * psize; |
775 | 788 | ||
776 | if (uvc_alloc_urb_buffers(video, size) < 0) | ||
777 | return -ENOMEM; | ||
778 | |||
779 | for (i = 0; i < UVC_URBS; ++i) { | 789 | for (i = 0; i < UVC_URBS; ++i) { |
780 | urb = usb_alloc_urb(npackets, gfp_flags); | 790 | urb = usb_alloc_urb(npackets, gfp_flags); |
781 | if (urb == NULL) { | 791 | if (urb == NULL) { |
@@ -814,25 +824,20 @@ static int uvc_init_video_bulk(struct uvc_video_device *video, | |||
814 | struct usb_host_endpoint *ep, gfp_t gfp_flags) | 824 | struct usb_host_endpoint *ep, gfp_t gfp_flags) |
815 | { | 825 | { |
816 | struct urb *urb; | 826 | struct urb *urb; |
817 | unsigned int pipe, i; | 827 | unsigned int npackets, pipe, i; |
818 | __u16 psize; | 828 | u16 psize; |
819 | __u32 size; | 829 | u32 size; |
820 | 830 | ||
821 | /* Compute the bulk URB size. Some devices set the maximum payload | ||
822 | * size to a value too high for memory-constrained devices. We must | ||
823 | * then transfer the payload accross multiple URBs. To be consistant | ||
824 | * with isochronous mode, allocate maximum UVC_MAX_ISO_PACKETS per bulk | ||
825 | * URB. | ||
826 | */ | ||
827 | psize = le16_to_cpu(ep->desc.wMaxPacketSize) & 0x07ff; | 831 | psize = le16_to_cpu(ep->desc.wMaxPacketSize) & 0x07ff; |
828 | size = video->streaming->ctrl.dwMaxPayloadTransferSize; | 832 | size = video->streaming->ctrl.dwMaxPayloadTransferSize; |
829 | video->bulk.max_payload_size = size; | 833 | video->bulk.max_payload_size = size; |
830 | if (size > psize * UVC_MAX_ISO_PACKETS) | ||
831 | size = psize * UVC_MAX_ISO_PACKETS; | ||
832 | 834 | ||
833 | if (uvc_alloc_urb_buffers(video, size) < 0) | 835 | npackets = uvc_alloc_urb_buffers(video, size, psize, gfp_flags); |
836 | if (npackets == 0) | ||
834 | return -ENOMEM; | 837 | return -ENOMEM; |
835 | 838 | ||
839 | size = npackets * psize; | ||
840 | |||
836 | if (usb_endpoint_dir_in(&ep->desc)) | 841 | if (usb_endpoint_dir_in(&ep->desc)) |
837 | pipe = usb_rcvbulkpipe(video->dev->udev, | 842 | pipe = usb_rcvbulkpipe(video->dev->udev, |
838 | ep->desc.bEndpointAddress); | 843 | ep->desc.bEndpointAddress); |
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index 027947ea9b6e..b2639878f9b2 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h | |||
@@ -296,10 +296,8 @@ struct uvc_xu_control { | |||
296 | 296 | ||
297 | /* Number of isochronous URBs. */ | 297 | /* Number of isochronous URBs. */ |
298 | #define UVC_URBS 5 | 298 | #define UVC_URBS 5 |
299 | /* Maximum number of packets per isochronous URB. */ | 299 | /* Maximum number of packets per URB. */ |
300 | #define UVC_MAX_ISO_PACKETS 40 | 300 | #define UVC_MAX_PACKETS 32 |
301 | /* Maximum frame size in bytes, for sanity checking. */ | ||
302 | #define UVC_MAX_FRAME_SIZE (16*1024*1024) | ||
303 | /* Maximum number of video buffers. */ | 301 | /* Maximum number of video buffers. */ |
304 | #define UVC_MAX_VIDEO_BUFFERS 32 | 302 | #define UVC_MAX_VIDEO_BUFFERS 32 |
305 | /* Maximum status buffer size in bytes of interrupt URB. */ | 303 | /* Maximum status buffer size in bytes of interrupt URB. */ |