aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2013-12-28 19:16:26 -0500
committerMauro Carvalho Chehab <m.chehab@samsung.com>2014-01-10 03:01:47 -0500
commitf5f894d19e2d40f1fb98a4799d85ed0904272cd6 (patch)
treefe82fe414e82de1b0254307b40131afc99f410a1
parent46c704d77f785974ce095b6cf0c71b92d1b06706 (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.c128
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)
174static int em28xx_init_audio_isoc(struct em28xx *dev) 164static 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
597static 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
646static int em28xx_audio_init(struct em28xx *dev) 618static 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;