Audio buffer mmap-ing on sh arch vs. cache aliasing problem

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Guys,
Recently I was investigating an issue with capturing audio using USBAudio Class device on a sh4-based board. "Bad voice quality" wasreported...
Finally I have traced the problem to something which is (unfortunately)well known to sh developers as a D-cache aliasing (or synonym) problem. 
Briefly speaking: due to some MMU design decisions, one can have twodifferent virtual address pointing to the same physical location, whichis fine, but going via different cache slots! So if there was a value of"0" in the memory and user "A" will write "1" there, user "B" will stillread "0"...
The solution is to ensure all TLB entries (so virtual memory areas) arebeginning from a 16kB-aligned virtual address. Otherwise it is necessaryto flush the cache between accesses from "A" and "B" sides.
And now. The USB Audio Class driver (sound/usb/usbaudio.c) is allocatingthe sound buffer like this...
static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, size_t size){[...]	runtime->dma_area = vmalloc(size);[...]}
... and vmalloc will return a page(4k)-aligned pointer, possibly not16k-aligned one. This is the source of all evil ;-) 
When using RW transfers everything is fine, as data is memcopied betweentwo independent buffers.
In a case of MMAP mode we will end up with such a situation:
1. The driver will memcpy data from an URB to the buffer. It willpopulate several cache lines. Let's call it a "kernel cache".2. As the library has mapped the non-16k-aligned address via differentcache line ("user cache"), it will read some rubbish from the physicalmemory, populating the "user cache" by the way.3. Some time later the "kernel cache" is flushed, writing the data tothe memory.4. Some new data from URB is entering "kernel cache".5. The library will access mmap-ed area again, going via the "usercache", which may or may not reflect the correct data (depending on thefact was the "user cache" flushed or not) etc.
Of course this cycle is completely not deterministic, so some of the"kernel cache" lines will be flushed before being accessed from userspace, other not... The final effect is... hmm... bizarre :-) First, ofcourse, you will get a (probably loud) glitch (rubbish from buffer'sunderlying memory, before the first valid data is written back), andthen something that could be described as an "echo" ;-) I mean - you arecapturing "1 2 3 4 5 6 7..." and the result is (G stands for Glitch ;-)"G 1 23 3 4 4 6 67..."
As a quick-and-dirty work-around I have modifiedsnd_pcm_alloc_vmalloc_buffer() to allocate always 12kB more and then use16k-aligned pointer:
static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs, size_t size){        struct snd_pcm_runtime *runtime = subs->runtime;        if (runtime->dma_addr) {                if (runtime->dma_bytes >= size)                        return 0; /* already large enough */                vfree((void *)runtime->dma_addr);        }        runtime->dma_addr = (unsigned long)vmalloc(size + 12 * 1024);        if (!runtime->dma_addr)                return -ENOMEM;        runtime->dma_area = (void *)ALIGN(runtime->dma_addr, 16 * 1024);        runtime->dma_bytes = size;        return 0;}
Of course it cannot be regarded as anything more as a hack. Anddefinitely not as a solution... So my question is:
Any idea how the "proper solution" should look like? I see no obviousmethod to get an arch-independent "mmap-compliant" buffer. This problemwas found on a sh arch, using an USB Audio Class device, however outthere some other architectures are suffering from this MMU "feature" aswell (ie. see http://docs.hp.com/en/B3906-90006/ch07s09.html) andpossibly other drivers could behave "wrongly" (quoted as the driver isactually innocent...)
To be honest I just have absolutely no idea what to do with thisall! :-O
I hope I was clear enough in the description... Any feedback, advise,idea etc. will be more than appreciated.
Cheers
Paweł
_______________________________________________Alsa-devel mailing listAlsa-devel@xxxxxxxxxxxxxxxxxxxx://mailman.alsa-project.org/mailman/listinfo/alsa-devel

[Index of Archives]     [ALSA User]     [Linux Audio Users]     [Kernel Archive]     [Asterisk PBX]     [Photo Sharing]     [Linux Sound]     [Video 4 Linux]     [Gimp]     [Yosemite News]

  Powered by Linux