From: "Frank Schäfer" <fschaefer.oss@googlemail.com>
To: Mauro Carvalho Chehab <m.chehab@samsung.com>
Cc: Mauro Carvalho Chehab <mchehab@redhat.com>,
Linux Media Mailing List <linux-media@vger.kernel.org>,
Mauro Carvalho Chehab <mchehab@infradead.org>
Subject: Re: [PATCH v4 21/22] [media] em28xx-audio: allocate URBs at device driver init
Date: Wed, 08 Jan 2014 20:14:39 +0100 [thread overview]
Message-ID: <52CDA39F.8030400@googlemail.com> (raw)
In-Reply-To: <20140108121010.3f82b447@samsung.com>
Am 08.01.2014 15:10, schrieb Mauro Carvalho Chehab:
> Em Tue, 07 Jan 2014 18:03:50 +0100
> Frank Schäfer <fschaefer.oss@googlemail.com> escreveu:
>
>> Am 05.01.2014 22:25, schrieb Mauro Carvalho Chehab:
>>> Em Sun, 05 Jan 2014 22:02:40 +0100
>>> Frank Schäfer <fschaefer.oss@googlemail.com> escreveu:
>>>
>>>> Am 04.01.2014 11:55, schrieb Mauro Carvalho Chehab:
>>>>> From: Mauro Carvalho Chehab <mchehab@redhat.com>
>>>> Is this line still correct ? ;)
>>>>
>>>>> 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>
>>>> Two Signed-off-by lines ? ;)
>>>>
>>>>> ---
>>>>> drivers/media/usb/em28xx/em28xx-audio.c | 128 ++++++++++++++++++--------------
>>>>> 1 file 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 @@
>>>>> *
>>>>> * Copyright (C) 2006 Markus Rechberger <mrechberger@gmail.com>
>>>>> *
>>>>> - * Copyright (C) 2007-2011 Mauro Carvalho Chehab <mchehab@redhat.com>
>>>>> + * Copyright (C) 2007-2014 Mauro Carvalho Chehab
>>>>> * - Port to work with the in-kernel driver
>>>>> * - Cleanups, fixes, alsa-controls, etc.
>>>>> *
>>>>> @@ -70,16 +70,6 @@ static int em28xx_deinit_isoc_audio(struct em28xx *dev)
>>>>> usb_kill_urb(urb);
>>>>> else
>>>>> usb_unlink_urb(urb);
>>>>> -
>>>>> - usb_free_coherent(dev->udev,
>>>>> - urb->transfer_buffer_length,
>>>>> - dev->adev.transfer_buffer[i],
>>>>> - urb->transfer_dma);
>>>>> -
>>>>> - dev->adev.transfer_buffer[i] = NULL;
>>>>> -
>>>>> - usb_free_urb(urb);
>>>>> - dev->adev.urb[i] = NULL;
>>>>> }
>>>>>
>>>>> return 0;
>>>>> @@ -174,53 +164,14 @@ static void em28xx_audio_isocirq(struct urb *urb)
>>>>> static int em28xx_init_audio_isoc(struct em28xx *dev)
>>>>> {
>>>>> int i, errCode;
>>>>> - const int sb_size = EM28XX_NUM_AUDIO_PACKETS *
>>>>> - EM28XX_AUDIO_MAX_PACKET_SIZE;
>>>>>
>>>>> dprintk("Starting isoc transfers\n");
>>>>>
>>>>> + /* Start streaming */
>>>>> for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
>>>>> - struct urb *urb;
>>>>> - int j, k;
>>>>> - void *buf;
>>>>> -
>>>>> - urb = usb_alloc_urb(EM28XX_NUM_AUDIO_PACKETS, GFP_ATOMIC);
>>>>> - if (!urb) {
>>>>> - em28xx_errdev("usb_alloc_urb failed!\n");
>>>>> - for (j = 0; j < i; j++) {
>>>>> - usb_free_urb(dev->adev.urb[j]);
>>>>> - kfree(dev->adev.transfer_buffer[j]);
>>>>> - }
>>>>> - return -ENOMEM;
>>>>> - }
>>>>> -
>>>>> - buf = usb_alloc_coherent(dev->udev, sb_size, GFP_ATOMIC,
>>>>> - &urb->transfer_dma);
>>>>> - if (!buf)
>>>>> - return -ENOMEM;
>>>>> - dev->adev.transfer_buffer[i] = buf;
>>>>> - memset(buf, 0x80, sb_size);
>>>>> -
>>>>> - urb->dev = dev->udev;
>>>>> - urb->context = dev;
>>>>> - urb->pipe = usb_rcvisocpipe(dev->udev, EM28XX_EP_AUDIO);
>>>>> - urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
>>>>> - urb->transfer_buffer = dev->adev.transfer_buffer[i];
>>>>> - urb->interval = 1;
>>>>> - urb->complete = em28xx_audio_isocirq;
>>>>> - urb->number_of_packets = EM28XX_NUM_AUDIO_PACKETS;
>>>>> - urb->transfer_buffer_length = sb_size;
>>>>> -
>>>>> - for (j = k = 0; j < EM28XX_NUM_AUDIO_PACKETS;
>>>>> - j++, k += EM28XX_AUDIO_MAX_PACKET_SIZE) {
>>>>> - urb->iso_frame_desc[j].offset = k;
>>>>> - urb->iso_frame_desc[j].length =
>>>>> - EM28XX_AUDIO_MAX_PACKET_SIZE;
>>>>> - }
>>>>> - dev->adev.urb[i] = urb;
>>>>> - }
>>>>> + memset(dev->adev.transfer_buffer[i], 0x80,
>>>>> + dev->adev.urb[i]->transfer_buffer_length);
>>>>>
>>>>> - for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
>>>>> errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC);
>>>>> if (errCode) {
>>>>> em28xx_errdev("submit of audio urb failed\n");
>>>>> @@ -643,13 +594,36 @@ static struct snd_pcm_ops snd_em28xx_pcm_capture = {
>>>>> .page = snd_pcm_get_vmalloc_page,
>>>>> };
>>>>>
>>>>> +static void em28xx_audio_free_urb(struct em28xx *dev)
>>>>> +{
>>>>> + int i;
>>>>> +
>>>>> + for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
>>>>> + struct urb *urb = dev->adev.urb[i];
>>>>> +
>>>>> + if (!dev->adev.urb[i])
>>>>> + continue;
>>>>> +
>>>>> + usb_free_coherent(dev->udev,
>>>>> + urb->transfer_buffer_length,
>>>>> + dev->adev.transfer_buffer[i],
>>>>> + urb->transfer_dma);
>>>>> +
>>>>> + usb_free_urb(urb);
>>>>> + dev->adev.urb[i] = NULL;
>>>>> + dev->adev.transfer_buffer[i] = NULL;
>>>>> + }
>>>>> +}
>>>>> +
>>>>> static int em28xx_audio_init(struct em28xx *dev)
>>>>> {
>>>>> struct em28xx_audio *adev = &dev->adev;
>>>>> struct snd_pcm *pcm;
>>>>> struct snd_card *card;
>>>>> static int devnr;
>>>>> - int err;
>>>>> + int err, i;
>>>>> + const int sb_size = EM28XX_NUM_AUDIO_PACKETS *
>>>>> + EM28XX_AUDIO_MAX_PACKET_SIZE;
>>>>>
>>>>> if (!dev->has_alsa_audio || dev->audio_ifnum < 0) {
>>>>> /* This device does not support the extension (in this case
>>>>> @@ -662,7 +636,8 @@ static int em28xx_audio_init(struct em28xx *dev)
>>>>>
>>>>> printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus "
>>>>> "Rechberger\n");
>>>>> - printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2007-2011 Mauro Carvalho Chehab\n");
>>>>> + printk(KERN_INFO
>>>>> + "em28xx-audio.c: Copyright (C) 2007-2014 Mauro Carvalho Chehab\n");
>>>>>
>>>>> err = snd_card_create(index[devnr], "Em28xx Audio", THIS_MODULE, 0,
>>>>> &card);
>>>>> @@ -704,6 +679,47 @@ static int em28xx_audio_init(struct em28xx *dev)
>>>>> em28xx_cvol_new(card, dev, "Surround", AC97_SURROUND_MASTER);
>>>>> }
>>>>>
>>>>> + /* Alloc URB and transfer buffers */
>>>>> + for (i = 0; i < EM28XX_AUDIO_BUFS; i++) {
>>>>> + struct urb *urb;
>>>>> + int j, k;
>>>>> + void *buf;
>>>>> +
>>>>> + urb = usb_alloc_urb(EM28XX_NUM_AUDIO_PACKETS, GFP_ATOMIC);
>>>>> + if (!urb) {
>>>>> + em28xx_errdev("usb_alloc_urb failed!\n");
>>>>> + em28xx_audio_free_urb(dev);
>>>>> + return -ENOMEM;
>>>>> + }
>>>>> + dev->adev.urb[i] = urb;
>>>>> +
>>>>> + buf = usb_alloc_coherent(dev->udev, sb_size, GFP_ATOMIC,
>>>>> + &urb->transfer_dma);
>>>>> + if (!buf) {
>>>>> + em28xx_errdev("usb_alloc_coherent failed!\n");
>>>>> + em28xx_audio_free_urb(dev);
>>>>> + return -ENOMEM;
>>>>> + }
>>>>> + dev->adev.transfer_buffer[i] = buf;
>>>>> +
>>>>> + urb->dev = dev->udev;
>>>>> + urb->context = dev;
>>>>> + urb->pipe = usb_rcvisocpipe(dev->udev, EM28XX_EP_AUDIO);
>>>>> + urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
>>>>> + urb->transfer_buffer = dev->adev.transfer_buffer[i];
>>>>> + urb->interval = 1;
>>>>> + urb->complete = em28xx_audio_isocirq;
>>>>> + urb->number_of_packets = EM28XX_NUM_AUDIO_PACKETS;
>>>>> + urb->transfer_buffer_length = sb_size;
>>>>> +
>>>>> + for (j = k = 0; j < EM28XX_NUM_AUDIO_PACKETS;
>>>>> + j++, k += EM28XX_AUDIO_MAX_PACKET_SIZE) {
>>>>> + urb->iso_frame_desc[j].offset = k;
>>>>> + urb->iso_frame_desc[j].length =
>>>>> + EM28XX_AUDIO_MAX_PACKET_SIZE;
>>>>> + }
>>>>> + }
>>>>> +
>>>>> err = snd_card_register(card);
>>>>> if (err < 0) {
>>>>> snd_card_free(card);
>>>>> @@ -728,6 +744,8 @@ static int em28xx_audio_fini(struct em28xx *dev)
>>>>> return 0;
>>>>> }
>>>>>
>>>>> + em28xx_audio_free_urb(dev);
>>>>> +
>>>>> if (dev->adev.sndcard) {
>>>>> snd_card_free(dev->adev.sndcard);
>>>>> dev->adev.sndcard = NULL;
>>>> I don't get it.
>>>> How does this patch reduce the memory allocation pressure ?
>>>> You are still allocating the same amount of memory.
>>> True, but it is not de-allocating/reallocating the same amount of
>>> memory every time, for every start/stop trigger. Depending on the
>>> userspace and the amount of available RAM, this could cause memory
>>> fragmentation.
>>>
>>> If you take a look at xHCI logs, you'll see that those operations
>>> are very expensive, and that it occurs too often.
>> How often is the device started/stopped ?
>> It's nothing that happens often/with a high freuqency, so is memeory
>> fragmentation really a problem here ?
> The trigger is called every time an underrun occurs. The thing is that
> the memory allocation, plus the start URB logic takes too long.
>
> With my test machine (an i7core with 4 cores, 8 threads, running at
> 2.4 GHz) and Kworld 305U (em2861), the time between receiving the trigger
> and having the first audio buffer is long enough to produce another underrun.
>
> At underrun, the driver will kill all existing URBs (with takes some time),
> deallocate memory. Then a new trigger will reallocate memory and re-submit
> URBs.
>
> That actually means that underrun->trigger off/trigger on->underrun loop
> happens several times per second, producing a crappy audio.
Ah, ok, I didn't expect it to happen that often.
No question then, the patch makes definitely sense.
Thanks for your explanations.
> At least on this machine, removing memory allocation from the trigger loop
> fixes the issue with Kworld 305U.
>
> Btw, I noticed the same bug in the past on an older test hardware and
> HVR-950.
>
> PS.: on a slower machine, this may eventually not be enough, and we may
> need to remove also the URB cancel/resubmit from the trigger loop.
> I have some patches for this too, as such patch were needed to isolate
> bugs when connected to a xHCI port (where URB kill doesn't seem to be
> working properly), but I'll submit such patches only if I can make em28xx
> work when connected to an xHCI 1.0 port, and while the USB core is not fixed.
I really need to buy a em28xx device with vendor audio interface.
My HVR930 has vendor audio, but - as you know - we don't support the
analog part of this device yet. :(
>
>>>> The only differences is that you already do this when the device isn't
>>>> used yet and don't free it when gets unused again.
>>>> IMHO that makes things worse, not better.
>>> Why is it worse?
>> Because you increase the memory usage of closed devices.
> So what? If someone plugged an em28xx device, it is because it is supposed
> to be used. Besides that, the amount of allocated memory is not big.
Sure, it's not a big problem.
>
>>> FYI, we're currently allocating DVB buffers at the device init too,
>>> due to the memory fragmentation problems. This is actually critical
>>> if you try to use it on an ARM with limited amount of RAM.
>> I was always wondering why.
>>
>> Ok, if this really solves problems on ARM, do it.
>> I assume it makes sense fix it for analog video, too. ;)
> Yes, it makes sense for analog video too. There are some additional steps
> to make em28xx v4l to work with ARM though. I'll eventually work on it if
> I have some time during this month.
Ok, great. :)
>
>>>> And yes, it makes the code that starts/stops streaming a way simpler.
>>>> But at the same time it makes the module initialization code the same
>>>> amount more complicated.
next prev parent reply other threads:[~2014-01-08 19:13 UTC|newest]
Thread overview: 80+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-01-04 10:55 [PATCH v4 00/22] em28xx: split analog part into a separate module Mauro Carvalho Chehab
2014-01-04 10:55 ` [PATCH v4 01/22] [media] em28xx: move some video-specific functions to em28xx-video Mauro Carvalho Chehab
2014-01-05 10:11 ` Frank Schäfer
2014-01-05 13:28 ` Mauro Carvalho Chehab
2014-01-04 10:55 ` [PATCH v4 02/22] [media] em28xx: some cosmetic changes Mauro Carvalho Chehab
2014-01-05 10:13 ` Frank Schäfer
2014-01-04 10:55 ` [PATCH v4 03/22] [media] em28xx: move analog-specific init to em28xx-video Mauro Carvalho Chehab
2014-01-05 10:26 ` Frank Schäfer
2014-01-05 14:40 ` Mauro Carvalho Chehab
2014-01-06 21:28 ` Frank Schäfer
2014-01-04 10:55 ` [PATCH v4 04/22] [media] em28xx: make em28xx-video to be a separate module Mauro Carvalho Chehab
2014-01-05 10:47 ` Frank Schäfer
2014-01-05 12:56 ` Mauro Carvalho Chehab
2014-01-05 15:18 ` Mauro Carvalho Chehab
2014-01-06 21:35 ` Frank Schäfer
2014-01-06 17:38 ` Frank Schäfer
2014-01-04 10:55 ` [PATCH v4 05/22] [media] em28xx: initialize analog I2C devices at the right place Mauro Carvalho Chehab
2014-01-05 10:48 ` Frank Schäfer
2014-01-04 10:55 ` [PATCH v4 06/22] [media] em28xx: add warn messages for timeout Mauro Carvalho Chehab
2014-01-05 10:51 ` Frank Schäfer
2014-01-05 13:05 ` Mauro Carvalho Chehab
2014-01-05 13:25 ` Mauro Carvalho Chehab
2014-01-04 10:55 ` [PATCH v4 07/22] [media] em28xx: improve extension information messages Mauro Carvalho Chehab
2014-01-05 10:55 ` Frank Schäfer
2014-01-05 13:08 ` Mauro Carvalho Chehab
2014-01-05 15:31 ` Mauro Carvalho Chehab
2014-01-06 17:44 ` Frank Schäfer
2014-01-06 18:17 ` Mauro Carvalho Chehab
2014-01-04 10:55 ` [PATCH v4 08/22] [media] em28xx: convert i2c wait completion logic to use jiffies Mauro Carvalho Chehab
2014-01-05 11:03 ` Frank Schäfer
2014-01-05 13:10 ` Mauro Carvalho Chehab
2014-01-06 17:48 ` Frank Schäfer
2014-01-04 10:55 ` [PATCH v4 09/22] [media] tvp5150: make read operations atomic Mauro Carvalho Chehab
2014-01-05 11:07 ` Frank Schäfer
2014-01-04 10:55 ` [PATCH v4 10/22] [media] tuner-xc2028: remove unused code Mauro Carvalho Chehab
2014-01-05 11:07 ` Frank Schäfer
2014-01-04 10:55 ` [PATCH v4 11/22] [media] em28xx: check if a device has audio earlier Mauro Carvalho Chehab
2014-01-05 11:12 ` Frank Schäfer
2014-01-05 13:22 ` Mauro Carvalho Chehab
2014-01-04 10:55 ` [PATCH v4 12/22] [media] em28xx: properly implement AC97 wait code Mauro Carvalho Chehab
2014-01-05 11:19 ` Frank Schäfer
2014-01-05 13:20 ` Mauro Carvalho Chehab
2014-01-05 15:44 ` Mauro Carvalho Chehab
2014-01-07 16:50 ` Frank Schäfer
2014-01-04 10:55 ` [PATCH v4 13/22] [media] em28xx: initialize audio latter Mauro Carvalho Chehab
2014-01-05 11:29 ` Frank Schäfer
2014-01-05 13:17 ` Mauro Carvalho Chehab
2014-01-07 17:00 ` Frank Schäfer
2014-01-08 14:29 ` Mauro Carvalho Chehab
2014-01-04 10:55 ` [PATCH v4 14/22] [media] em28xx: unify module version Mauro Carvalho Chehab
2014-01-05 11:33 ` Frank Schäfer
2014-01-04 10:55 ` [PATCH v4 15/22] [media] em28xx: Fix em28xx deplock Mauro Carvalho Chehab
2014-01-05 11:38 ` Frank Schäfer
2014-01-04 10:55 ` [PATCH v4 16/22] [media] em28xx: use a better value for I2C timeouts Mauro Carvalho Chehab
2014-01-05 20:38 ` Frank Schäfer
2014-01-05 20:57 ` Mauro Carvalho Chehab
2014-01-07 17:15 ` Frank Schäfer
2014-01-08 14:39 ` Mauro Carvalho Chehab
2014-01-04 10:55 ` [PATCH v4 17/22] [media] em28xx-i2c: Fix error code for I2C error transfers Mauro Carvalho Chehab
2014-01-05 20:40 ` Frank Schäfer
2014-01-06 9:55 ` Mauro Carvalho Chehab
2014-01-07 17:28 ` Frank Schäfer
2014-01-08 11:55 ` Mauro Carvalho Chehab
2014-01-08 19:37 ` Frank Schäfer
2014-01-04 10:55 ` [PATCH v4 18/22] [media] em28xx: don't return -ENODEV for I2C xfer errors Mauro Carvalho Chehab
2014-01-05 20:49 ` Frank Schäfer
2014-01-06 10:37 ` Mauro Carvalho Chehab
2014-01-04 10:55 ` [PATCH v4 19/22] [media] em28xx: cleanup I2C debug messages Mauro Carvalho Chehab
2014-01-05 20:54 ` Frank Schäfer
2014-01-04 10:55 ` [PATCH v4 20/22] [media] em28xx: use usb_alloc_coherent() for audio Mauro Carvalho Chehab
2014-01-05 20:57 ` Frank Schäfer
2014-01-04 10:55 ` [PATCH v4 21/22] [media] em28xx-audio: allocate URBs at device driver init Mauro Carvalho Chehab
2014-01-05 21:02 ` Frank Schäfer
2014-01-05 21:25 ` Mauro Carvalho Chehab
2014-01-06 16:25 ` Mauro Carvalho Chehab
2014-01-07 17:03 ` Frank Schäfer
2014-01-08 14:10 ` Mauro Carvalho Chehab
2014-01-08 19:14 ` Frank Schäfer [this message]
2014-01-04 10:55 ` [PATCH v4 22/22] [media] em28xx: retry read operation if it fails Mauro Carvalho Chehab
2014-01-05 21:06 ` Frank Schäfer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=52CDA39F.8030400@googlemail.com \
--to=fschaefer.oss@googlemail.com \
--cc=linux-media@vger.kernel.org \
--cc=m.chehab@samsung.com \
--cc=mchehab@infradead.org \
--cc=mchehab@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).