linux-media.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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.


  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).