Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Laurent Pinchart and committed by
Mauro Carvalho Chehab
e01117c8 29135878

+66 -32
+64 -32
drivers/media/video/uvc/uvc_video.c
··· 554 554 } 555 555 556 556 /* 557 + * Free transfer buffers. 558 + */ 559 + static 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 + */ 581 + static 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 604 * Uninitialize isochronous/bulk URBs and free transfer buffers. 558 605 */ 559 - static void uvc_uninit_video(struct uvc_video_device *video) 606 + static void uvc_uninit_video(struct uvc_video_device *video, int free_buffers) 560 607 { 561 608 struct urb *urb; 562 609 unsigned int i; ··· 613 566 continue; 614 567 615 568 usb_kill_urb(urb); 616 - /* urb->transfer_buffer_length is not touched by USB core, so 617 - * we can use it here as the buffer length. 618 - */ 619 - if (video->urb_buffer[i]) { 620 - usb_buffer_free(video->dev->udev, 621 - urb->transfer_buffer_length, 622 - video->urb_buffer[i], urb->transfer_dma); 623 - video->urb_buffer[i] = NULL; 624 - } 625 - 626 569 usb_free_urb(urb); 627 570 video->urb[i] = NULL; 628 571 } 572 + 573 + if (free_buffers) 574 + uvc_free_urb_buffers(video); 629 575 } 630 576 631 577 /* ··· 650 610 651 611 size = npackets * psize; 652 612 613 + if (uvc_alloc_urb_buffers(video, size) < 0) 614 + return -ENOMEM; 615 + 653 616 for (i = 0; i < UVC_URBS; ++i) { 654 617 urb = usb_alloc_urb(npackets, gfp_flags); 655 618 if (urb == NULL) { 656 - uvc_uninit_video(video); 657 - return -ENOMEM; 658 - } 659 - 660 - video->urb_buffer[i] = usb_buffer_alloc(video->dev->udev, 661 - size, gfp_flags, &urb->transfer_dma); 662 - if (video->urb_buffer[i] == NULL) { 663 - usb_free_urb(urb); 664 - uvc_uninit_video(video); 619 + uvc_uninit_video(video, 1); 665 620 return -ENOMEM; 666 621 } 667 622 ··· 667 632 urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; 668 633 urb->interval = ep->desc.bInterval; 669 634 urb->transfer_buffer = video->urb_buffer[i]; 635 + urb->transfer_dma = video->urb_dma[i]; 670 636 urb->complete = uvc_video_complete; 671 637 urb->number_of_packets = npackets; 672 638 urb->transfer_buffer_length = size; ··· 707 671 if (size > psize * UVC_MAX_ISO_PACKETS) 708 672 size = psize * UVC_MAX_ISO_PACKETS; 709 673 674 + if (uvc_alloc_urb_buffers(video, size) < 0) 675 + return -ENOMEM; 676 + 710 677 pipe = usb_rcvbulkpipe(video->dev->udev, ep->desc.bEndpointAddress); 711 678 712 679 for (i = 0; i < UVC_URBS; ++i) { 713 680 urb = usb_alloc_urb(0, gfp_flags); 714 681 if (urb == NULL) { 715 - uvc_uninit_video(video); 716 - return -ENOMEM; 717 - } 718 - 719 - video->urb_buffer[i] = usb_buffer_alloc(video->dev->udev, 720 - size, gfp_flags, &urb->transfer_dma); 721 - if (video->urb_buffer[i] == NULL) { 722 - usb_free_urb(urb); 723 - uvc_uninit_video(video); 682 + uvc_uninit_video(video, 1); 724 683 return -ENOMEM; 725 684 } 726 685 ··· 723 692 video->urb_buffer[i], size, uvc_video_complete, 724 693 video); 725 694 urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; 695 + urb->transfer_dma = video->urb_dma[i]; 726 696 727 697 video->urb[i] = urb; 728 698 } ··· 798 766 if ((ret = usb_submit_urb(video->urb[i], gfp_flags)) < 0) { 799 767 uvc_printk(KERN_ERR, "Failed to submit URB %u " 800 768 "(%d).\n", i, ret); 801 - uvc_uninit_video(video); 769 + uvc_uninit_video(video, 1); 802 770 return ret; 803 771 } 804 772 } ··· 823 791 return 0; 824 792 825 793 video->frozen = 1; 826 - uvc_uninit_video(video); 794 + uvc_uninit_video(video, 0); 827 795 usb_set_interface(video->dev->udev, video->streaming->intfnum, 0); 828 796 return 0; 829 797 } ··· 952 920 int ret; 953 921 954 922 if (!enable) { 955 - uvc_uninit_video(video); 923 + uvc_uninit_video(video, 1); 956 924 usb_set_interface(video->dev->udev, 957 925 video->streaming->intfnum, 0); 958 926 uvc_queue_enable(&video->queue, 0);
+2
drivers/media/video/uvc/uvcvideo.h
··· 602 602 603 603 struct urb *urb[UVC_URBS]; 604 604 char *urb_buffer[UVC_URBS]; 605 + dma_addr_t urb_dma[UVC_URBS]; 606 + unsigned int urb_size; 605 607 606 608 __u8 last_fid; 607 609 };