diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-12-28 19:16:26 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2014-01-10 03:01:47 -0500 |
commit | f5f894d19e2d40f1fb98a4799d85ed0904272cd6 (patch) | |
tree | fe82fe414e82de1b0254307b40131afc99f410a1 | |
parent | 46c704d77f785974ce095b6cf0c71b92d1b06706 (diff) |
[media] em28xx-audio: allocate URBs at device driver init
Instead of allocating/deallocating URBs and transfer buffers
every time stream is started/stopped, just do it once.
That reduces the memory allocation pressure and makes the
code that start/stop streaming a way simpler.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
-rw-r--r-- | drivers/media/usb/em28xx/em28xx-audio.c | 128 |
1 files changed, 73 insertions, 55 deletions
diff --git a/drivers/media/usb/em28xx/em28xx-audio.c b/drivers/media/usb/em28xx/em28xx-audio.c index e5120430ec80..30ee389a07f0 100644 --- a/drivers/media/usb/em28xx/em28xx-audio.c +++ b/drivers/media/usb/em28xx/em28xx-audio.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 2006 Markus Rechberger <mrechberger@gmail.com> | 4 | * Copyright (C) 2006 Markus Rechberger <mrechberger@gmail.com> |
5 | * | 5 | * |
6 | * Copyright (C) 2007-2011 Mauro Carvalho Chehab <mchehab@redhat.com> | 6 | * Copyright (C) 2007-2014 Mauro Carvalho Chehab |
7 | * - Port to work with the in-kernel driver | 7 | * - Port to work with the in-kernel driver |
8 | * - Cleanups, fixes, alsa-controls, etc. | 8 | * - Cleanups, fixes, alsa-controls, etc. |
9 | * | 9 | * |
@@ -70,16 +70,6 @@ static int em28xx_deinit_isoc_audio(struct em28xx *dev) | |||
70 | usb_kill_urb(urb); | 70 | usb_kill_urb(urb); |
71 | else | 71 | else |
72 | usb_unlink_urb(urb); | 72 | usb_unlink_urb(urb); |
73 | |||
74 | usb_free_coherent(dev->udev, | ||
75 | urb->transfer_buffer_length, | ||
76 | dev->adev.transfer_buffer[i], | ||
77 | urb->transfer_dma); | ||
78 | |||
79 | dev->adev.transfer_buffer[i] = NULL; | ||
80 | |||
81 | usb_free_urb(urb); | ||
82 | dev->adev.urb[i] = NULL; | ||
83 | } | 73 | } |
84 | 74 | ||
85 | return 0; | 75 | return 0; |
@@ -174,53 +164,14 @@ static void em28xx_audio_isocirq(struct urb *urb) | |||
174 | static int em28xx_init_audio_isoc(struct em28xx *dev) | 164 | static int em28xx_init_audio_isoc(struct em28xx *dev) |
175 | { | 165 | { |
176 | int i, errCode; | 166 | int i, errCode; |
177 | const int sb_size = EM28XX_NUM_AUDIO_PACKETS * | ||
178 | EM28XX_AUDIO_MAX_PACKET_SIZE; | ||
179 | 167 | ||
180 | dprintk("Starting isoc transfers\n"); | 168 | dprintk("Starting isoc transfers\n"); |
181 | 169 | ||
170 | /* Start streaming */ | ||
182 | for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { | 171 | for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { |
183 | struct urb *urb; | 172 | memset(dev->adev.transfer_buffer[i], 0x80, |
184 | int j, k; | 173 | dev->adev.urb[i]->transfer_buffer_length); |
185 | void *buf; | ||
186 | |||
187 | urb = usb_alloc_urb(EM28XX_NUM_AUDIO_PACKETS, GFP_ATOMIC); | ||
188 | if (!urb) { | ||
189 | em28xx_errdev("usb_alloc_urb failed!\n"); | ||
190 | for (j = 0; j < i; j++) { | ||
191 | usb_free_urb(dev->adev.urb[j]); | ||
192 | kfree(dev->adev.transfer_buffer[j]); | ||
193 | } | ||
194 | return -ENOMEM; | ||
195 | } | ||
196 | |||
197 | buf = usb_alloc_coherent(dev->udev, sb_size, GFP_ATOMIC, | ||
198 | &urb->transfer_dma); | ||
199 | if (!buf) | ||
200 | return -ENOMEM; | ||
201 | dev->adev.transfer_buffer[i] = buf; | ||
202 | memset(buf, 0x80, sb_size); | ||
203 | |||
204 | urb->dev = dev->udev; | ||
205 | urb->context = dev; | ||
206 | urb->pipe = usb_rcvisocpipe(dev->udev, EM28XX_EP_AUDIO); | ||
207 | urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; | ||
208 | urb->transfer_buffer = dev->adev.transfer_buffer[i]; | ||
209 | urb->interval = 1; | ||
210 | urb->complete = em28xx_audio_isocirq; | ||
211 | urb->number_of_packets = EM28XX_NUM_AUDIO_PACKETS; | ||
212 | urb->transfer_buffer_length = sb_size; | ||
213 | |||
214 | for (j = k = 0; j < EM28XX_NUM_AUDIO_PACKETS; | ||
215 | j++, k += EM28XX_AUDIO_MAX_PACKET_SIZE) { | ||
216 | urb->iso_frame_desc[j].offset = k; | ||
217 | urb->iso_frame_desc[j].length = | ||
218 | EM28XX_AUDIO_MAX_PACKET_SIZE; | ||
219 | } | ||
220 | dev->adev.urb[i] = urb; | ||
221 | } | ||
222 | 174 | ||
223 | for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { | ||
224 | errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC); | 175 | errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC); |
225 | if (errCode) { | 176 | if (errCode) { |
226 | em28xx_errdev("submit of audio urb failed\n"); | 177 | em28xx_errdev("submit of audio urb failed\n"); |
@@ -643,13 +594,36 @@ static struct snd_pcm_ops snd_em28xx_pcm_capture = { | |||
643 | .page = snd_pcm_get_vmalloc_page, | 594 | .page = snd_pcm_get_vmalloc_page, |
644 | }; | 595 | }; |
645 | 596 | ||
597 | static void em28xx_audio_free_urb(struct em28xx *dev) | ||
598 | { | ||
599 | int i; | ||
600 | |||
601 | for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { | ||
602 | struct urb *urb = dev->adev.urb[i]; | ||
603 | |||
604 | if (!dev->adev.urb[i]) | ||
605 | continue; | ||
606 | |||
607 | usb_free_coherent(dev->udev, | ||
608 | urb->transfer_buffer_length, | ||
609 | dev->adev.transfer_buffer[i], | ||
610 | urb->transfer_dma); | ||
611 | |||
612 | usb_free_urb(urb); | ||
613 | dev->adev.urb[i] = NULL; | ||
614 | dev->adev.transfer_buffer[i] = NULL; | ||
615 | } | ||
616 | } | ||
617 | |||
646 | static int em28xx_audio_init(struct em28xx *dev) | 618 | static int em28xx_audio_init(struct em28xx *dev) |
647 | { | 619 | { |
648 | struct em28xx_audio *adev = &dev->adev; | 620 | struct em28xx_audio *adev = &dev->adev; |
649 | struct snd_pcm *pcm; | 621 | struct snd_pcm *pcm; |
650 | struct snd_card *card; | 622 | struct snd_card *card; |
651 | static int devnr; | 623 | static int devnr; |
652 | int err; | 624 | int err, i; |
625 | const int sb_size = EM28XX_NUM_AUDIO_PACKETS * | ||
626 | EM28XX_AUDIO_MAX_PACKET_SIZE; | ||
653 | 627 | ||
654 | if (!dev->has_alsa_audio || dev->audio_ifnum < 0) { | 628 | if (!dev->has_alsa_audio || dev->audio_ifnum < 0) { |
655 | /* This device does not support the extension (in this case | 629 | /* This device does not support the extension (in this case |
@@ -662,7 +636,8 @@ static int em28xx_audio_init(struct em28xx *dev) | |||
662 | 636 | ||
663 | printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus " | 637 | printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus " |
664 | "Rechberger\n"); | 638 | "Rechberger\n"); |
665 | printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2007-2011 Mauro Carvalho Chehab\n"); | 639 | printk(KERN_INFO |
640 | "em28xx-audio.c: Copyright (C) 2007-2014 Mauro Carvalho Chehab\n"); | ||
666 | 641 | ||
667 | err = snd_card_create(index[devnr], "Em28xx Audio", THIS_MODULE, 0, | 642 | err = snd_card_create(index[devnr], "Em28xx Audio", THIS_MODULE, 0, |
668 | &card); | 643 | &card); |
@@ -704,6 +679,47 @@ static int em28xx_audio_init(struct em28xx *dev) | |||
704 | em28xx_cvol_new(card, dev, "Surround", AC97_SURROUND_MASTER); | 679 | em28xx_cvol_new(card, dev, "Surround", AC97_SURROUND_MASTER); |
705 | } | 680 | } |
706 | 681 | ||
682 | /* Alloc URB and transfer buffers */ | ||
683 | for (i = 0; i < EM28XX_AUDIO_BUFS; i++) { | ||
684 | struct urb *urb; | ||
685 | int j, k; | ||
686 | void *buf; | ||
687 | |||
688 | urb = usb_alloc_urb(EM28XX_NUM_AUDIO_PACKETS, GFP_ATOMIC); | ||
689 | if (!urb) { | ||
690 | em28xx_errdev("usb_alloc_urb failed!\n"); | ||
691 | em28xx_audio_free_urb(dev); | ||
692 | return -ENOMEM; | ||
693 | } | ||
694 | dev->adev.urb[i] = urb; | ||
695 | |||
696 | buf = usb_alloc_coherent(dev->udev, sb_size, GFP_ATOMIC, | ||
697 | &urb->transfer_dma); | ||
698 | if (!buf) { | ||
699 | em28xx_errdev("usb_alloc_coherent failed!\n"); | ||
700 | em28xx_audio_free_urb(dev); | ||
701 | return -ENOMEM; | ||
702 | } | ||
703 | dev->adev.transfer_buffer[i] = buf; | ||
704 | |||
705 | urb->dev = dev->udev; | ||
706 | urb->context = dev; | ||
707 | urb->pipe = usb_rcvisocpipe(dev->udev, EM28XX_EP_AUDIO); | ||
708 | urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; | ||
709 | urb->transfer_buffer = dev->adev.transfer_buffer[i]; | ||
710 | urb->interval = 1; | ||
711 | urb->complete = em28xx_audio_isocirq; | ||
712 | urb->number_of_packets = EM28XX_NUM_AUDIO_PACKETS; | ||
713 | urb->transfer_buffer_length = sb_size; | ||
714 | |||
715 | for (j = k = 0; j < EM28XX_NUM_AUDIO_PACKETS; | ||
716 | j++, k += EM28XX_AUDIO_MAX_PACKET_SIZE) { | ||
717 | urb->iso_frame_desc[j].offset = k; | ||
718 | urb->iso_frame_desc[j].length = | ||
719 | EM28XX_AUDIO_MAX_PACKET_SIZE; | ||
720 | } | ||
721 | } | ||
722 | |||
707 | err = snd_card_register(card); | 723 | err = snd_card_register(card); |
708 | if (err < 0) { | 724 | if (err < 0) { |
709 | snd_card_free(card); | 725 | snd_card_free(card); |
@@ -728,6 +744,8 @@ static int em28xx_audio_fini(struct em28xx *dev) | |||
728 | return 0; | 744 | return 0; |
729 | } | 745 | } |
730 | 746 | ||
747 | em28xx_audio_free_urb(dev); | ||
748 | |||
731 | if (dev->adev.sndcard) { | 749 | if (dev->adev.sndcard) { |
732 | snd_card_free(dev->adev.sndcard); | 750 | snd_card_free(dev->adev.sndcard); |
733 | dev->adev.sndcard = NULL; | 751 | dev->adev.sndcard = NULL; |